绕着显式专业化的标准限制行走

时间:2017-08-09 23:34:18

标签: c++ templates c++14

我正在努力以一种漂亮的方式编写成员函数的可变参数模板的显式特化。问题是标准禁止非命名空间作用域中的显式特化,如here所述。 MSVC允许这样的事情,但是GCC(可能还有一些其他更加标准的编译器)没有 Reproduction of the problem(让我们说它只是为了简单而打印)

struct A
{
   template<typename ...Args>
   A(Args... args) { print(int(args)...); }

   template<typename ...Rest>
   void print(int first, Rest... rest) const
   {
       std::cout << first;
       print(int(rest)...);
   }
   template<>
   void print(int first) const { std::cout << first; }
};

int main()
{
   A(1, 3, 2, 5, 7, 4);
}

在提供的链接中,更简单的情况主要是因为只有一个模板参数和缺少“递归”。我无法找到一种方法来实现这种工作,而不是以流血的方式 除了提供再现之外,我也遇到了完全相同的问题,但是使用构造函数会使这更复杂......

1 个答案:

答案 0 :(得分:1)

写一个正常的过载?

void print(int first) const { std::cout << first; }

Demo

除此之外,假设您的示例实际上有点复杂,您可能需要查看已标记的调度:

struct A
{
    template<class... Args>
    struct A_tag{};

    template<typename ...Args>
    A(Args... args) { print(A_tag<Args...>{}, int(args)...); }

    template<typename ...Rest>
    void print(A_tag<int, Rest...>, int first, Rest... rest) const
    {
        std::cout << first;
        print(A_tag<Rest...>{}, int(rest)...);
    }

    void print(A_tag<int>, int first) const { std::cout << first; }
};

Demo 2

标记调度方法背后的想法仍然是利用重载,但它确实使重载接受专门针对特定类型的tag结构。

标记的功能可以隐藏为private,您可以展示漂亮的非标记功能。