morganstanley/binlog

[BUG] static constexpr const class member compile failed

Closed this issue · 5 comments

Hello, everyone,

Thanks for your great source code sharing in github, I am new to binlog, and trying to use it to improve performance in my project.

Well, I meet one very simple case which could not compile success, code is attached.
So is it possible a binlog BUG? I use default cmake compile options. my desktop is ubuntu20 and g++7.5.0 and x86 cpu.
BTW, glog is OK for this case. and set(CMAKE_CXX_STANDARD 17) also could solve this issue. Any idea?

#include <binlog/binlog.hpp>

struct A {
static constexpr const char* VE = "world";
};

int main()
{
BINLOG_INFO("Hello {}!", A::VE);
// LOG(ERROR) << "Hello " << A::VE << std::endl; This is ok if only glog
return 0;
}

hi, what's the compiler error that you get? Without setting CMAKE_CXX_STANDARD, what's the C++ standard being used?

oh, sorry for forgetting to attach the error log, here it is. @erenon .
CMakeFiles/Bug.dir/example/Bug.cpp.o: In function main':
/home/murphy/Project/binlog/example/Bug.cpp:10: undefined reference to A::VE' /home/murphy/Project/binlog/example/Bug.cpp:10: undefined reference to A::VE'
collect2: error: ld returned 1 exit status
CMakeFiles/Bug.dir/build.make:96: recipe for target 'Bug' failed
make[2]: *** [Bug] Error 1
CMakeFiles/Makefile2:1190: recipe for target 'CMakeFiles/Bug.dir/all' failed
make[1]: *** [CMakeFiles/Bug.dir/all] Error 2
Makefile:145: recipe for target 'all' failed
make: *** [all] Error 2`

And I didn't change the CMakeLists.txt, and I use std::cout << __cplusplus;, it shows 201402, so it is C++14.
The CMakeLists.txt setting of CMAKE_CXX_STANDARD is:
set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard (11/14/17/20/...)") # -std=c++14

Thanks for you quick reply!

Just to compare test, if only use std::cout, it is also no compile issue:

#include <binlog/binlog.hpp>
#include <iostream>

struct A {
static constexpr const char* VE = "world";
};

int main()
{
std::cout << "hello: " << A::VE << std::endl;
// BINLOG_INFO("Hello {}!", A::VE);
// LOG(ERROR) << "Hello " << A::VE << std::endl; This is ok if only glog
return 0;
}

I'm unable to reproduce this with either C++14 or C++17.

$ g++ --version
g++ (GCC) 11.2.0

Perhaps g++7.5.0 has a different interpretation of the standard. From the error message, I suspect that because the binlog macro ODR uses the argument (it takes its reference), gcc looks for an object with an address. Without a local repro, I can only guess possible workarounds, e.g:

BINLOG_INFO("Hello {}!", std::string_view(A::VE));

I'm unable to reproduce this with either C++14 or C++17.

$ g++ --version
g++ (GCC) 11.2.0

Perhaps g++7.5.0 has a different interpretation of the standard. From the error message, I suspect that because the binlog macro ODR uses the argument (it takes its reference), gcc looks for an object with an address. Without a local repro, I can only guess possible workarounds, e.g:

BINLOG_INFO("Hello {}!", std::string_view(A::VE));

Thanks for suggestion, yes, I could use C++17 or add declaration by constexpr const char* VE; out scope of the struct definition to avoid this compile issue.
I didnot try higher version of g++, well, maybe it is just a compiler bug... may could close this if it is not related to binlog implementation.