I have some confusions regarding static constexpr member variables in C++11.
In first.hpp
template<typename T> struct cond_I { static constexpr T value = 0; }; // specialization template<typename T> struct cond_I< std::complex<T> > { static constexpr std::complex<T> value = {0,1}; }; In main() function
cout << cond_I<double>::value << endl; // this works fine cout << cond_I< complex<double> >::value << endl; // linker error However if I add the following line to first.hpp everything works fine.
template<typename T1> constexpr std::complex<T1> cond_I< std::complex<T1> >::value; What I understand (I may be wrong) is, that cond_I< std::complex<double> >::value needs a definition, but in the previous case it only has the declaration. But then what about cond_I<double>::value? Why it does not require a definition?
Again, in another header file, second.hpp, I have:
In second.hpp
// empty struct template<typename T> struct eps { }; // special cases template<> struct eps<double> { static constexpr double value = 1.0e-12; }; template<> struct eps<float> { static constexpr float value = 1.0e-6; }; In this case, following codes works perfectly without any definition of eps<>::value.
In main() function
cout << eps<double>::value << endl; // works fine cout << eps<float>::value << endl; // works fine Can someone please explain me the different behaviors of static constexpr member variables, in these scenarios?
These behaviors are also the same for gcc-5.2 and clang-3.6.
ostream::operator<<(ostream&, const complex<T> &)passes by reference, this is considered odr-use of the argument, therefore you need a definition (for the reference to refer to).floatordoubleare passed by value, so the second code works. Thank you.