Search code examples
c++visual-studiotemplatespartial-specialization

Specialize member template struct by template parameters of class


I have a class like

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; } };
};

what I want to realize is to cout "1" when P==N, however I found when I run

TEST<0>::test<0, 10>::Run();

it still gives 0.

Later I found when there is only one parameter in the template list it works:

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; } };
};

though it looks simple, but what is the mechanism there, and how should I make it work when there two parameters?

EDIT

  1. As m.s. has pointed out that, this code can do its job on a gcc compiler on Wandbox, but it just fails on my vs2013. Anyone knows why?

  2. As Petr points out, the funny thing is that on MSVS, when P==I the result is "1".

  3. When I changed the code to:

    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(); gives "1".


Solution

  • As mentioned by other answers, this problem definitely looks to be a bug in VS. Before MS fix this bug, I found one solution to realize the same function:

    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; } };
    };
    

    which gives "1" when P==N, otherwise "0". The above solution has passed tests on both VS2013 and gcc5.2.0.