1

以下编译按预期运行和执行:

#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)

显然,这两个语句在语义上是等价的。我在哪里可以找到如何确定模板原型相等的正式定义?

这显然是某种程度的词汇等价而不是语义等价。

4

1 回答 1

2

我找不到标准的任何部分明确指定类模板(或类模板及其成员的外联定义中的说明符)的重新声明何时相同。

编译器实际上遵循 C++11 14.5.6.1/5+6 中指定的函数模板的重新声明规则:

5如果两个包含模板参数的函数定义满足一个定义规则 (3.2),则两个涉及模板参数的表达式被认为是等价的,[模板参数重命名] 除外。6 如果两个函数模板在同一范围内声明、具有相同的名称、具有相同的模板参数列表,并且使用上述规则比较涉及模板参数的表达式,则它们具有等效的返回类型和参数列表,则它们是等效的

但是,我找不到任何规则使其适用于非类型模板参数类型中的表达式以重新声明类模板。

于 2015-06-15T12:27:41.103 回答