The following compiles runs and executes as expected:
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <type_traits>
class Freaky {
public:
template<
typename UNSIGNED_TYPE,
typename std::enable_if<(sizeof(UNSIGNED_TYPE)>=sizeof(int)),int>::type X = 0
>
static UNSIGNED_TYPE copyThing(int x) ;
};
template<
typename UNSIGNED_TYPE,
typename std::enable_if<(sizeof(UNSIGNED_TYPE)>=sizeof(int)),int>::type X
>
UNSIGNED_TYPE Freaky::copyThing(int x) {
UNSIGNED_TYPE r(0);
std::memcpy(&r,&x,sizeof(int));//Please ignore. Not the point of the question...
return r;
}
int main(int argc, char*argv[]) {
std::cout << "The answer is ... " <<
Freaky::copyThing<unsigned long>(10)<<std::endl;
return EXIT_SUCCESS;
}
Specimen output (actual output may depend on endian-ness and integer sizes):
The answer is .... 10
The following won't compile and complains about the prototype for the implementation of copyThing()
doesn't match the one declared in the class.
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <type_traits>
class Freaky {
public:
template<
typename UNSIGNED_TYPE,
typename std::enable_if<(sizeof(UNSIGNED_TYPE)>=sizeof(int)),int>::type X = 0
>
static UNSIGNED_TYPE copyThing(int x) ;
};
template<
typename UNSIGNED_TYPE,
typename std::enable_if<(sizeof(int)<=sizeof(UNSIGNED_TYPE)),int>::type X
>
UNSIGNED_TYPE Freaky::copyThing(int x) {
UNSIGNED_TYPE r(0);
std::memcpy(&r,&x,sizeof(int));//Please ignore. Not the point of the question...
return r;
}
int main(int argc, char*argv[]) {
std::cout << "The answer is ... " <<
Freaky::copyThing<unsigned long>(10)<<std::endl;
return EXIT_SUCCESS;
}
The only difference between the two is that sizeof(UNSIGNED_TYPE)>=sizeof(int)
has been replaced with sizeof(int)<=sizeof(UNSIGNED_TYPE)
in that implementation.
Obviously the two statements are semantically equivalent. Where can I find the formal definition of how template prototypes are determined to be equal?
It's clearly some level of lexical equivalence rather than semantic equivalence.
I can't find any part of the standard that explicitly specifies when redeclarations of class templates (or a class template and its specifier in an out-of-line definition of members) are the same.
Compilers actually follow the rules for redeclaration of function template, as specified in C++11 14.5.6.1/5+6:
I can't find any rule that makes this apply to expressions in the types of non-type template parameters for redeclarations of class templates, though.