通过 class 的模板参数专门化成员模板结构
Specialize member template struct by template parameters of class
我有一个class喜欢
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; } };
};
我想实现的是在 P==N
时 cout
“1”,但是我发现 运行
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”。
以下完整代码(我删除了 __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
2013 年 Visual Studio,并且
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.
中的错误
正如其他答案所提到的,这个问题看起来肯定是VS中的一个错误。
在微软修复这个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上都通过了测试
我有一个class喜欢
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; } };
};
我想实现的是在 P==N
时 cout
“1”,但是我发现 运行
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”。
以下完整代码(我删除了 __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
2013 年 Visual Studio,并且
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.
正如其他答案所提到的,这个问题看起来肯定是VS中的一个错误。 在微软修复这个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上都通过了测试