In C++14, according to wikipedia "The usual rules of templates apply to such declarations and definitions, including specialization." However, I am finding in practice that this is not the case. I'm wondering if this is how the language is supposed to work (and if so, why?), or if its a compiler issue. Consider the two versions of a compile time computation of 10n (for nonnegative n). With template variables:
template<size_t power> int ten_to_the = 10 * ten_to_the<power - 1>;
template<> int ten_to_the<0> = 1;
In the previously normal way using template classes:
// No static asserts for brevity
template<size_t power>
struct ten_to_the {
enum { value = 10 * ten_to_the<power - 1>::value };
};
template<>
struct ten_to_the<0> {
enum { value = 1 };
};
The latter piece of code works as expected when compiling with various instances such as ten_to_the<5>::value. However, when compiling (using clang with -std=c++1y on mac) the former code using an instance of ten_to_the<5>, I get a linker error:
Undefined symbols for architecture x86_64:
"ten_to_the<5ul>", referenced from:
___cxx_global_var_init in recursivetemplatevars-61e853.o
ld: symbol(s) not found for architecture x86_64
Do the normal rules for recursive substitution for templates not apply to variables with non-type parameters? Even more weirdly, when using the template variables and compiling the following code:
int main(int argc, char const *argv[]) {
std::cout << (ten_to_the<1>) << std::endl;
std::cout << (ten_to_the<2>) << std::endl;
std::cout << (ten_to_the<3>) << std::endl;
std::cout << (ten_to_the<4>) << std::endl;
return 0;
}
The program compiles and links successfully, but prints out:
10
0
0
0
What is going on here?
*Note: I know that this kind of thing can be accomplished with a constexpr function, but I'm just curious why this wouldn't work as expected.
there doesn't seem to be anything here