C++ Template Equivalence of Prototypes

171 Views Asked by At

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.

1

There are 1 best solutions below

0
On BEST ANSWER

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:

5 Two expressions involving template parameters are considered equivalent if two function definitions containing the expressions would satisfy the one definition rule (3.2), except [template parameter renaming]. 6 Two function template are equivalent if they are declared in the same scope, have the same name, have identical template parameter lists, and have return types and parameter lists that are equivalent using the rules described above to compare expressions involving template parameters.

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.