通过类的模板参数来专门化成员模板结构

时间:2015-10-26 07:13:08

标签: c++ visual-studio templates partial-specialization

我有一个像

这样的课程
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; } };
};

虽然它看起来很简单,但那里的机制是什么,当有两个参数时我应该如何使它工作?

修改

  1. 作为m.s.已经指出,这段代码可以在Wandbox上的gcc编译器上完成它的工作,但它在我的vs2013上失败了。谁知道为什么?

  2. 正如彼得指出的那样,有趣的是,在MSVS上,当P==I结果为“1”时。

  3. 当我将代码更改为:

    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; } };
    };
    
  4. TEST<int>::test<int, 10>::Run();给出“1”。

2 个答案:

答案 0 :(得分: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

on 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中的一个错误。

答案 1 :(得分:1)

正如其他答案所提到的,这个问题肯定是VS中的一个错误。 在MS修复此错误之前,我找到了一个实现相同功能的解决方案:

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的测试。