具有变异模板模板参数的方法的部分专业化
partial specialization of a method with variadic templated template parameter
我有一个代码,该代码成功编译(G 4.9.2(:
#include <iostream>
#include <utility>
// 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;
}
int
main(int argc, char** argv)
{
xxx<uint8_t> x1;
std::cout << "xxx<uint8_t> => ";
foo(x1);
xxx<uint16_t> x2;
std::cout << "xxx<uint16_t> => ";
foo(x2);
xxx<uint8_t,uint16_t> x3;
std::cout << "xxx<uint8_t,uint16_t> => ";
foo(x3);
std::pair<uint8_t,uint16_t> x4;
std::cout << "std::pair<uint8_t,uint16_t> => ";
foo(x4);
return 0;
}
和生产:
xxx<uint8_t> => xxx<uint8_t>
xxx<uint16_t> => xxx<TT>
xxx<uint8_t,uint16_t> => xxx<TTs...>
std::pair<uint8_t,uint16_t> => T<TTs...>
现在我想在课堂内使用这些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;
}
这会产生汇编错误:
test_ko.cc:24:1: error: prototype for ‘void abc::foo(xxx<TTs ...>&)’ does not match any in class ‘abc’
abc::foo(xxx<TTs...>& arg)
^
test_ko.cc:10:5: error: candidate is: template<template<class ...> class T, class ... TTs> void abc::foo(T<TTs ...>&)
foo(T<TTs...>& arg)
^
test_ko.cc:31:1: error: prototype for ‘void abc::foo(xxx<TT>&)’ does not match any in class ‘abc’
abc::foo(xxx<TT>& arg)
^
test_ko.cc:10:5: error: candidate is: template<template<class ...> class T, class ... TTs> void abc::foo(T<TTs ...>&)
foo(T<TTs...>& arg)
我想要Foo方法的专业化,而不是在ABC类中声明新的签名(因为有一个带有模板的类,库的一部分和单独的专业化,以后声明为XXX类(。
看来,带有方法的代码类似于具有功能的代码,但是我在这里遇到了错误。我做错了什么?
// 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;
}
这是不是专业化。这是一个不同的模板函数,其名称foo
与上述模板函数重载。
// specialization for non-variadic templated xxx
template<typename TT> void
foo(xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}
这是不是专业化。这是一个不同的模板函数,其名称foo
与上述模板函数过载。
// specialization for xxx<uint8_t>
template<> void
foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}
这是上述模板函数之一的完整专业化。我认为第三个,但我不会押注钱。(我相信,如果您打电话给foo
,则专门针对哪种模板xxx<uint8_t>&
(。
而不是这个完整的专业化,我会写:
inline foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}
这再次是foo
的全新超载。超负荷远不及完整功能专业的古怪。
没有部分模板函数propece 。
这解释了为什么您尝试使用相同语法专业的方法不起作用。没有诸如部分模板成员函数专业之类的东西。
您要么必须在类本身中写入过载,要么派遣到其他上下文。
什么"出了问题",是错误的直接原因是您的初始代码引入了 new Overloads 。您不允许在类定义之外引入新方法的新过载,因此编译器指出了您的错误。
这是一种有用的技术。我们在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;
}
我们的foo
方法扩展到foo
朋友。
然后,我们在与abc
相同的名称空间中添加代码:
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找到的。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 如何使用默认参数等选择模板专业化
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 派生类中纯虚拟基方法的专业化
- 函数模板部分专业化-有什么解决方法吗
- 模板类专业化具有成员变量和方法的默认值
- 具有变异模板模板参数的方法的部分专业化
- 将方法添加到类模板专业化中
- 纯虚拟方法的模板专业化
- 模板类方法的专业化
- 模板方法enable_if专业化