以下编译按预期运行并执行:
#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)
。
显然这两个陈述是语义等价的。 我在哪里可以找到模板原型如何被确定为正确的正式定义?
显然,某种程度的词汇等价而不是语义等价。
答案 0 :(得分:2)
我无法找到标准的任何部分,这些部分明确指定何时重新声明类模板(或类模板及其在成员的外部定义中的说明符)是相同的。
编译器实际上遵循重新声明函数模板的规则,如C ++ 11 14.5.6.1/5+6中所述:
5如果包含表达式的两个函数定义满足一个定义规则(3.2),则[模板参数重命名]除外,两个涉及模板参数的表达式被视为等效。 6两个函数模板等效如果它们在同一范围内声明,具有相同的名称,具有相同的模板参数列表,并且具有使用上述规则进行比较的等效的返回类型和参数列表涉及模板参数的表达式。
我无法找到任何规则,使其适用于非类型模板参数类型中的表达式,以便重新声明类模板。