通过类的模板参数特化成员模板结构
Posted
技术标签:
【中文标题】通过类的模板参数特化成员模板结构【英文标题】:Specialize member template struct by template parameters of class 【发布时间】:2015-10-26 07:13:07 【问题描述】:我有一门课
template <unsigned N>
class TEST
public:
template <unsigned P, unsigned I> struct test static __forceinline void Run() std::cout << 0 << std::endl; ;
template <unsigned I> struct test <N, I> static __forceinline void Run() std::cout << 1 << std::endl; ;
;
我想实现的是cout
“1”当P==N
,但是我在运行时发现
TEST<0>::test<0, 10>::Run();
它仍然给出0
。
后来我发现当模板列表中只有一个参数时它起作用了:
template <unsigned N>
class TEST
public:
template <unsigned P> struct test static __forceinline void Run() std::cout << 0 << std::endl; ;
template <> struct test <N> static __forceinline void Run() std::cout << 1 << std::endl; ;
;
虽然看起来很简单,但其中的机制是什么,当有两个参数时我应该如何使其工作?
编辑
作为 m.s.已经指出,这段代码可以在Wandbox 上的 gcc 编译器上完成它的工作,但它在我的 vs2013 上失败了。有人知道为什么吗?
正如 Petr 所指出的,有趣的是在 MSVS 上,当P==I
结果为“1”时。
当我将代码更改为:
template <typename N>
class TEST
public:
template <typename P, unsigned I> struct test static __forceinline void Run() std::cout << 0 << std::endl; ;
template <unsigned I> struct test <N, I> static __forceinline void Run() std::cout << 1 << std::endl; ;
;
TEST<int>::test<int, 10>::Run();
给出“1”。
【问题讨论】:
原始代码的输出为“1”:melpon.org/wandbox/permlink/CyW5VmcwsFteOys0 @m.s.我测试过,很神奇。我的 vs2013 编译得到了不同的结果。 @m.s,在 VS2013 上也为我输出 0,在 gcc 4.8.2 上为我输出 1。 最搞笑的是TEST<2>::test<10, 10>::Run();
在MSVS2013上为我打印1
!
@Petr 是的,这和我一样。当“P==I”为“1”时。
【参考方案1】:
以下完整代码(我删除了__forceinline
以使其与gcc兼容):
#include <iostream>
template <unsigned N>
class TEST
public:
template <unsigned P, unsigned I> struct test static void Run() std::cout << 0 << std::endl; ;
template <unsigned I> struct test <N, I> static void Run() std::cout << 1 << std::endl; ;
// template <unsigned I> struct test <I, I> static void Run() std::cout << 2 << std::endl; ;
;
int main()
TEST<2>::test<2, 10>::Run();
TEST<2>::test<10, 10>::Run();
return 0;
输出
0
1
在 Visual Studio 2013 上,以及
1
0
在 gcc 4.8.2 上。
如果您取消注释注释行,gcc 将给出预期结果1 2
,而 VS 无法编译并出现以下错误:
1>source.cpp(12): error C2752: 'TEST<2>::test<10,10>' : more than one partial specialization matches the template argument list
1> source.cpp(7): could be 'TEST<N>::test<N,I>'
1> source.cpp(8): or 'TEST<N>::test<I,I>'
因此,MSVS 似乎将(第一个)专业化用于P==I
,而不是N==P
。这绝对看起来是 Visual Studio 中的一个错误。
【讨论】:
【参考方案2】:正如其他答案所提到的,这个问题肯定看起来是 VS 中的一个错误。 在MS修复这个bug之前,我找到了一个实现相同功能的解决方案:
template <unsigned N>
class TEST
public:
template <unsigned P, unsigned I, bool Specialize = (N==P)> struct test static void Run() std::cout << 0 << std::endl; ;
template <unsigned P, unsigned I> struct test <P,I,true> static void Run() std::cout << 1 << std::endl; ;
;
P==N
时给出“1”,否则给出“0”。
上述方案在VS2013和gcc5.2.0上均通过测试。
【讨论】:
以上是关于通过类的模板参数特化成员模板结构的主要内容,如果未能解决你的问题,请参考以下文章
C++模板编程中只特化模板类的一个成员函数(花样特化一个成员函数)
Clang 是不是正确拒绝仅通过特化定义类模板的嵌套类的代码?