When I try to compile this,
#include <iostream>
struct K{
const static int a = 5;
};
int main(){
K k;
std::cout << std::min(k.a, 7);
}
I get following. Both gcc
and clang
gives similar error:
/tmp/x-54e820.o: In function `main':
x.cc:(.text+0xa): undefined reference to `K::a'
clang-3.7: error: linker command failed with exit code 1 (use -v to see invocation)
if I do following, it compiles without problem. Is this related to the way std::min
is written?
#include <iostream>
struct K{
const static int a = 5;
};
int main(){
K k;
std::cout << std::min((int) k.a, 7); // <= here is the change!!!
}
another way to avoid the error is if I do my own min()
:
template <class T>
T min(T const a, T const b){
return a < b ? a : b;
}
C-like preprocessor MIN
also works OK.
You can fix the errors by including the source code file that contains the definitions as part of the compilation. Alternatively, you can pass . obj files or . lib files that contain the definitions to the linker.
Linker Errors: These error occurs when after compilation we link the different object files with main's object using Ctrl+F9 key(RUN). These are errors generated when the executable of the program cannot be generated. This may be due to wrong function prototyping, incorrect header files.
Linker errors occur when the linker is trying to put all the pieces of a program together to create an executable, and one or more pieces are missing. Typically, this can happen when an object file or libraries can't be found by the linker. Fixing linker errors can be tricky.
So when we try to assign it a value in the main function, the linker doesn't find the symbol and may result in an “unresolved external symbol” or “undefined reference”. The way to fix this error is to explicitly scope the variable using '::' outside the main before using it.
std::min
accepts arguments by reference. Binding a reference to an object means that the object is odr-used (there is a code sample in [basic.def.odr]/2 pretty much the same as your sample).
However in the (int)k.a
case, k.a
is not odr-used; because it is performing lvalue-to-rvalue conversion which yields a constant expression. (There are a few other conditions here too but your code is OK).
If an object is odr-used then there must be exactly one definition of it; with no diagnostic required for violating this rule. So the first case may or may not be accepted; and the second case must be accepted.
In your own version of min
, it takes arguments by value, which is similar to the (int)k.a
case - the only action taken on k.a
there is rvalue conversion to initialize the parameter of your min
.
You can read the full set of rules about odr-use in section [basic.def.odr] of a C++ standard draft.
This question is asked quite often. I believe it's a bug in clang. (see correction in comments)a
is being detected as a constant expression too early and the compiler is not generating a definition of it.
std::min
takes its arguments by const reference, so a definition must exist.
#include <iostream>
struct K{
const static int a = 5;
};
int main(){
K k;
std::cout << std::min(k.a, 7);
}
Here's a portable workaround alternative:
#include <iostream>
struct K{
constexpr static int a() { return 5; }
};
int main(){
K k;
std::cout << std::min(k.a(), 7);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With