Opened 7 years ago

Closed 6 years ago

#11998 closed Bugs (fixed)

Static const variables cannot be logged

Reported by: Hendrik Schall <torres@…> Owned by: Andrey Semashev
Milestone: To Be Determined Component: log
Version: Boost 1.60.0 Severity: Problem
Keywords: log static const Cc:

Description

Static const variables cannot be logged for me any more. I am using RHEL 7.1 and the Intel icpc for my programms (boost compiled with gcc 4.8.3)

The following code does not work in 1.60.0 but does in 1.59.0 Maybe it has to do with the changes regarding formatting_ostream #11549 or #11545

Code:

/* 
 * File:   main.cpp
 * Author: hschall
 *
 * Created on February 18, 2016, 6:53 AM
 */

#include <cstdlib>
#define BOOST_LOG_DYN_LINK
#include <boost/log/trivial.hpp>

class TestStaticError{
    public:
        static void doLog(){
          BOOST_LOG_TRIVIAL(debug) << myVar;
        }
    private:
        static const unsigned int myVar = 1337;
};

class TestStaticWorking{
    public:
        static void doLog(){
            BOOST_LOG_TRIVIAL(debug) << (unsigned int)myVar;
        }
    private:
        static const unsigned int myVar = 1337;
};

using namespace std;

/*
 * 
 */
int main(int argc, char** argv){

  TestStaticWorking::doLog(); // Works
  
  // Works in 1.59.0
  //TestStaticError::doLog(); // main.cpp:21: undefined reference to `TestStaticError::myVar' 
  
  return 0;
}

Change History (4)

comment:1 by Andrey Semashev, 7 years ago

I don't think this is a bug in the library.

The static constant members have to be defined in some (one) translation unit, which gives them storage. In C++11 and later this is required if a reference to the variable is taken, which happens when you call the operator<<. In pre-C++11 versions of the language, IIRC, the definition is required unconditionally.

The type conversion that you use as a workaround makes the operator<< bind the reference to a temporary, that's why it works. I'm not sure how it works differently in 1.59 since I don't see any changes that could lead to that but there were such changes since 1.58 - the operator<< overloads could have been chosen differently before, which would result in not taking the reference.

However, I can see that your use case could be useful, and I'll see if I can support it in the future.

comment:2 by Hendrik Schall <torres@…>, 7 years ago

The workaround is just to show that this behaviour relates to the static variable.

I compile with C++11 (but tested it also with C++98 and C++14). I did test it with the GCC (4.8.3) now aswell, same behaviour.

Wether it is a bug or not, it depends on the boost library version, which is strange.

comment:3 by o.z, 6 years ago

I see similar problem using bitfields:

I took the example from http://www.boost.org/doc/libs/1_61_0/libs/log/example/doc/tutorial_trivial_flt.cpp and added a bitfield print:

#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>

namespace logging = boost::log;

//[ example_tutorial_trivial_with_filtering
void init()
{
    logging::core::get()->set_filter
    (
        logging::trivial::severity >= logging::trivial::info
    );
}


struct BF {
                unsigned int b : 8;
                BF() : b(0) {}
};


int main(int, char*[])
{
    init();

    BF bf;
    BOOST_LOG_TRIVIAL(info) << "An informational severity message " << bf.b;

    return 0;
}
//]

With boost 1.60 I got a compilation error:

cannot bind bitfield 'bf.BF::b' to 'unsigned int&'

With boost 1.57 the code is compiled and run (prints: [2016-09-19 20:21:33.018112] [0x000007fd1d5be672] [info] An informational severity message 0)

comment:4 by Andrey Semashev, 6 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.