bgo*_*dst 5 c++ templates conditional-compilation template-meta-programming
假设我有一个简单的nullary模板函数模板化在一个参数上,有两个特化,一个用于unsigned long,一个用于size_t(内容不重要):
template<typename T> T f(void);
template<> unsigned long f<unsigned long>(void) { return 1; }
template<> size_t f<size_t>(void) { return 2; }
Run Code Online (Sandbox Code Playgroud)
我的理解是该类型的确切定义size_t是依赖于平台的,因此它可能相同或不相同unsigned long.在我目前的平台上(Cygwin g ++ 5.2.0在Windows 10上进行64位编译-std=gnu++1y)这两种类型看起来是等价的,所以上面的代码无法编译:
../test.cpp:51:19: error: redefinition of ‘T f() [with T = long unsigned int]’
template<> size_t f<size_t>(void) { return 2; }
^
../test.cpp:50:26: note: ‘T f() [with T = long unsigned int]’ previously declared here
template<> unsigned long f<unsigned long>(void) { return 1; }
^
Run Code Online (Sandbox Code Playgroud)
根据我的想法,这个问题可以通过简单地禁用size_t函数定义来解决,因为任何试图调用的代码f<size_t>()都会自动解析f<unsigned long>().但是应该为定义size_t不同的平台启用该功能unsigned long.
我已经阅读了一些关于模板元编程和SFINAE的内容,我一直在玩这样的事情:
std::enable_if<(sizeof(size_t) > sizeof(unsigned long))>::type
Run Code Online (Sandbox Code Playgroud)
但我不确定如何使用这样的片段来禁用全局函数定义,如果可能的话.
那么,有没有办法使用模板元编程来有条件地禁用全局函数定义?或者,更一般地说,我是在正确的轨道上,还是走错了路?
这在任何情况下都有效,但它有点单调乏味,并且不适合大量的专业化:
template<typename T
, std::enable_if_t<!std::is_same<T, unsigned long>::value
&& !std::is_same<T, size_t>::value>* = nullptr>
T f() { return 1; }
template<typename T
, std::enable_if_t<std::is_same<T, unsigned long>::value>* = nullptr>
T f() { return 2; }
template<typename T
, std::enable_if_t<std::is_same<T, size_t>::value
&& !std::is_same<T, unsigned long>::value>* = nullptr>
T f() { return 3; }
Run Code Online (Sandbox Code Playgroud)
这个想法:不专门但是过载,只有在签名合适时才启用重载(同时禁用其他签名).
此外,为了使其更易于维护,应该将逻辑检查外包到另一个合适的类中.
演示:
int main()
{
std::cout<<f<int>()<<std::endl;
std::cout<<f<unsigned long>()<<std::endl;
std::cout<<f<size_t>()<<std::endl;
std::cout<<f<unsigned long long>()<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
它打印:
1
2
2
1
Run Code Online (Sandbox Code Playgroud)
所以它似乎size_t == unsigned long在coliru上.
| 归档时间: |
|
| 查看次数: |
284 次 |
| 最近记录: |