C++ 可变模板参数方法的部分特化

C++ 可变模板参数方法的部分特化,c++,c++11,c++14,C++,C++11,C++14,我有一个成功编译的代码(g++4.9.2): #包括 #包括 //任意可变模板参数的一般函数 模板 无效的 foo(T&arg) { std::cout xxx xxx=>xxx xxx=>xxx std::pair=>T 现在我想将这些foo方法放在一个类中,并编写: #include <iostream> #include <utility> class abc { public: // general function for any variadic

我有一个成功编译的代码(g++4.9.2):

#包括
#包括
//任意可变模板参数的一般函数
模板
无效的
foo(T&arg)
{
std::cout xxx
xxx=>xxx
xxx=>xxx
std::pair=>T
现在我想将这些foo方法放在一个类中,并编写:

#include <iostream>
#include <utility>

class abc
{
public:
    // general function for any variadic templated argument
    template<template<typename ...> class T, typename ...TTs>
    void
    foo(T<TTs...>& arg)
    {
        std::cout << "T<TTs...>" << std::endl;
    }
};

template<typename ...Ts>
struct xxx
{
    // not important
};

// specialization for only variadic templated xxx
template<typename ...TTs> void
abc::foo(xxx<TTs...>& arg)
{
    std::cout << "xxx<TTs...>" << std::endl;
}

// specialization for non-variadic templated xxx
template<typename TT> void
abc::foo(xxx<TT>& arg)
{
    std::cout << "xxx<TT>" << std::endl;
}

// specialization for xxx<uint8_t>
template<> void
abc::foo(xxx<uint8_t>& arg)
{
    std::cout << "xxx<uint8_t>" << std::endl;
}

int
main(int argc, char** argv)
{
    abc p;

    xxx<uint8_t> x1;
    std::cout << "xxx<uint8_t> => ";
    p.foo(x1);

    xxx<uint16_t> x2;
    std::cout << "xxx<uint16_t> => ";
    p.foo(x2);

    xxx<uint8_t,uint16_t> x3;
    std::cout << "xxx<uint8_t,uint16_t> => ";
    p.foo(x3);

    std::pair<uint8_t,uint16_t> x4;
    std::cout << "std::pair<uint8_t,uint16_t> => ";
    p.foo(x4);

    return 0;
}
#包括
#包括
abc班
{
公众:
//任意可变模板参数的一般函数
模板
无效的
foo(T&arg)
{
标准::cout
这不是专门化。这是另一个模板函数,其名称
foo
与上述模板函数重载

// specialization for xxx<uint8_t>
template<> void
foo(xxx<uint8_t>& arg)
{
  std::cout << "xxx<uint8_t>" << std::endl;
}
这又是一个全新的重载
foo
。重载远没有全功能专门化那么古怪

没有部分模板函数专门化这样的事情

这就解释了为什么用相同语法专门化方法的尝试不起作用。也没有部分模板成员函数专门化

您要么在类本身中编写重载,要么将其分派到不同的上下文

“出错”和导致错误的直接原因是您的初始代码引入了新的重载。不允许您在类定义之外引入方法的新重载,因此编译器指出了您的错误


下面是一个有用的技巧。我们在abc

// general function for any variadic templated argument
  template<template<typename ...> class T, typename ...TTs>
  void foo(T<TTs...>& arg)
  {
    return foo(*this, arg);
  }
private:
  template<template<typename ...> class T, typename ...TTs>
  friend void foo(abc& self, T<TTs...>& arg)
  {
    std::cout << "T<TTs...>" << std::endl;
  }
template<typename ...TTs> void
foo(abc& self, xxx<TTs...>& arg)
{
  std::cout << "xxx<TTs...>" << std::endl;
}

template<typename TT> void
foo(abc& self, xxx<TT>& arg)
{
  std::cout << "xxx<TT>" << std::endl;
}

inline void foo(abc& self, xxx<uint8_t>& arg)
{
  std::cout << "xxx<uint8_t>" << std::endl;
}

当调用
abc::foo
时,可以通过ADL找到它们。

不可能部分专门化函数模板。没有这样的事情。你可以重载函数模板,并完全专门化它,但如果你认为你是部分专门化的,那你就错了。一般来说,如果你摆脱了完全专门化,你会身体好一点。
// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void
foo(T<TTs...>& arg)
{
  std::cout << "T<TTs...>" << std::endl;
}
template<typename ...Ts>
struct xxx
{
  // not important
};

// specialization for only variadic templated xxx
template<typename ...TTs> void
foo(xxx<TTs...>& arg)
{
  std::cout << "xxx<TTs...>" << std::endl;
}
// specialization for non-variadic templated xxx
template<typename TT> void
foo(xxx<TT>& arg)
{
  std::cout << "xxx<TT>" << std::endl;
}
// specialization for xxx<uint8_t>
template<> void
foo(xxx<uint8_t>& arg)
{
  std::cout << "xxx<uint8_t>" << std::endl;
}
inline foo(xxx<uint8_t>& arg)
{
  std::cout << "xxx<uint8_t>" << std::endl;
}
// general function for any variadic templated argument
  template<template<typename ...> class T, typename ...TTs>
  void foo(T<TTs...>& arg)
  {
    return foo(*this, arg);
  }
private:
  template<template<typename ...> class T, typename ...TTs>
  friend void foo(abc& self, T<TTs...>& arg)
  {
    std::cout << "T<TTs...>" << std::endl;
  }
template<typename ...TTs> void
foo(abc& self, xxx<TTs...>& arg)
{
  std::cout << "xxx<TTs...>" << std::endl;
}

template<typename TT> void
foo(abc& self, xxx<TT>& arg)
{
  std::cout << "xxx<TT>" << std::endl;
}

inline void foo(abc& self, xxx<uint8_t>& arg)
{
  std::cout << "xxx<uint8_t>" << std::endl;
}