Следующие компиляции запускаются и выполняются, как и ожидалось:
#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;
}
Вывод образца (фактический вывод может зависеть от порядкового номера и целочисленных размеров):
The answer is .... 10
Следующее не скомпилируется и жалуется на прототип для реализации copyThing()
не соответствует заявленному в классе.
#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;
}
Единственная разница между ними состоит в том, что sizeof(UNSIGNED_TYPE)>=sizeof(int)
был заменен на sizeof(int)<=sizeof(UNSIGNED_TYPE)
в этой реализации.
Очевидно, что два утверждения семантически эквивалент.
Где я могу найти формальное определение того, как прототипы шаблонов определяются как равные?
Это явно некоторый уровень лексической эквивалентности, а не семантической эквивалентности.
Я не могу найти какую-либо часть стандарта, которая явно указывает, когда переопределения шаблонов классов (или шаблон класса и его спецификатор в внешнем определении членов) совпадают.
Компиляторы фактически следуют правилам переопределения шаблона функции, как указано в C ++ 11 14.5.6.1/5+6:
5 Рассматриваются два выражения с параметрами шаблона. эквивалент если два определения функции, содержащие выражения, удовлетворяют одному правилу определения (3.2), за исключением [переименование параметра шаблона].
6 Два функциональных шаблона эквивалент если они объявлены в одной и той же области видимости, имеют одинаковое имя, идентичные списки параметров шаблона и имеют возвращаемые типы и списки параметров, которые эквивалентны с использованием правил, описанных выше, для сравнения выражений, включающих параметры шаблона.
Однако я не могу найти ни одного правила, которое бы применило это к выражениям в типах нетиповых параметров шаблонов для переопределений шаблонов классов.