Please see the code:
#include <iostream>
#include <typeinfo>
template<int N>
struct C
{
static constexpr int n = N;
using this_type_1 = C<n>;
using this_type_2 = C<N>;
static this_type_1* p_1;
static this_type_2* p_2;
};
template<int N>
//C<N>* C<N>::p_1; // <--- error pattern
typename C<N>::this_type_1* C<N>::p_1; // <--- ok pattern
template<int N>
C<N>* C<N>::p_2; // ok
int main(){
std::cerr
<< typeid(C<0>).name() << "\n"
<< typeid(C<0>::this_type_1).name() << "\n"
<< typeid(C<0>::this_type_2).name() << "\n"
;
}
It can compile with g++-4.7.1 and clang++-3.1. But it cannot compile with the commented-out error pattern.
g++ error message is:
test.cpp:15:13: error: conflicting declaration ‘C<N>* C<N>::p_1’
test.cpp:10:23: error: ‘C<N>::p_1’ has a previous declaration as ‘C<N>::this_type_1* C<N>::p_1’
test.cpp:15:13: error: declaration of ‘C<N>::this_type_1* C<N>::p_1’ outside of class is not definition [-fpermissive]
clang++ error message is:
test.cpp:15:13: error: redefinition of 'p_1' with a different type
C<N>* C<N>::p_1; // error
^
test.cpp:10:23: note: previous definition is here
static this_type_1* p_1;
^
1 error generated.
Luckily, I found out a working pattern. But I don’t know why The error pattern cannot be compiled. Please tell me the reason on the basis of the C++ language specification.
The two possible definitions for
C<N>::p_1are not as equivalent as they appear, becauseC<N>::nmay be explicitly specialized at any time before the first instantiation for a givenN.If the compiler had accepted that definition of
C<N>::p_1, it would be possible for its declared type to be incorrect.