成员函数模板的参数数量取决于一个积分模板参数
Member function template with the number of parameters depending on an integral template parameter
我有以下类模板:
template<class T, unsigned N>
class MyClass;
其中T
是某种类型,N
是组件的数量。可以使用MyClass{a1, a2, a3}
初始化类,其中参数的数量等于N
。
我想添加一个MyClass
的成员函数模板(让我们将其命名为foo
),它将满足以下要求:
- 它由另一种类型
T2
(即template<class T2> void foo(..)
)模板化 - 它接受足够的数据来构造
MyClass<T,N>
,但不能少也不能多。违反此规则将导致编译时错误 - 从参数的类型推导出CCD_ 10。也就是说,我希望可以调用
foo({a1, a2, a3})
或foo(a1, a2, a3)
或类似的功能,而无需每次都键入<double>
或MyClass<double,N>
是否有实现该功能的方法,以满足上述要求?
我已经考虑和/或尝试了以下解决方案:
1) 显而易见的一个:
...
template<class T2>
void foo(MyClass<T2, N> arg);
...
a.foo({1,2,3}); //compile-time error
原则上不起作用,因为支撑初始值设定项列表是非推导上下文,因此它们不能推导出任何类型。这真是太不幸了,如果能奏效,我会很高兴的。
2) initializer_list
原则上无法工作,因为它无法在编译时检查参数的数量。
3) 可变模板魔术
类似以下功能的东西会很简洁:
template<class...T2, class std::enable_if<sizeof...(T2) == N, int>::type = 0>
void foo(T2... args);
..
foo(1,2,3);
然而,我无法使它发挥作用——T2仍然无法推导出来。也许有人知道为什么?我使用了GCC4.7 20120121快照。
4) 丑陋的一个
本质上,这与上面的相同,只是扩展为不同N的几个重载。我最好将MyClass
重新实现为不同N
的一组专门化,而不是使用这个。
template<class T2, class std::enable_if<N == 1, int>::type = 0>
void fun(T2 a1); //if N == 1
template<class T2, ..>
void fun(T2 a1, T2 a2); //if N == 2
template<class T2, ..>
void fun(T2 a1, T2 a2, T2 a3); //if N == 3
...
第三个变体的第二个非类型参数的前缀应该是typename
,而不是class
:
template<class...T2, typename std::enable_if<sizeof...(T2) == N, int>::type = 0>
void foo(T2... args);
..
foo(1,2,3);
检查
Gcc 4.7.0 snapshots在模板方面有一些错误,我想,如果你用Gcc 4.6.2/1尝试它,它会起作用。
为什么不使用static_assert
?
template <typename T, size_t N>
class MyClass
{
public:
template <typename... Args>
void foo(Args&&... args)
{
static_assert(sizeof...(Args) == N, "Wrong number of arguments.");
// Rest of the implementation.
}
};
可能是这样的:
#include <utility>
#include <type_traits>
template <typename T, unsigned int N>
class MyClass
{
template <typename ...Args>
typename std::enable_if<std::is_constructible<MyClass<T, N>, Args...>::value>::type
foo(Args &&... args)
{
// for example:
MyClass<T, N> m(std::forward<Args>(args)...);
// ...
}
};
只有当MyClass
有一个直接接受相关参数的构造函数(如MyClass(A1, A2, A3)
)时,这才有效,但我认为如果MyClass
有一个需要初始化器列表的构造函数,这就不起作用,如果MyClass
是一个需要大括号初始化的聚合,这也不起作用。
也就是说,看起来你的MyClass
不可能接受初始值设定项列表,因为你说过它必须精确地接受N
参数,而IL不能承诺这一点。
可能是,基于您的第三个变体,您可以从初始值设定项列表中提取第一个参数,并通过它来推断类型
template<class U, class...T2, class std::enable_if<sizeof...(T2) == N-1, int>::type = 0>
void foo(U u, T2... args)
{
MyClass<U, N>({u, args...});
}
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何制作一个将函数作为参数的类方法
- 修改函数中的指针(将另一个指针作为参数传递)
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 构造函数在退出函数时无法初始化一个参数
- 在C++中声明一个函数时,它需要有函数本身的参数吗
- visual是否可以在c++中创建一个接收无限数量相同类型(或至少相当数量)参数的函数
- 如何将一个类的函数作为另一个类的另一个函数的参数传递
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- 运算符重载:"operator+"必须采用零个或一个参数
- 是否可以在C++中有一个"generic"模板参数,该参数可以是非类型模板参数或类型?
- 如果需要转换,我可以在读取参数的同时将其移动到另一个参数吗?
- 如何在另一个函数中使用返回值作为参数?
- 如果模板参数是另一个模板的实例化,则键入特征测试
- 将参数一个接一个地传递,或通过将它们包裹在数组,结构或元组中
- 如何给一个参数一个由其他参数的函数确定的默认值
- C++如何给一个参数一个特定的枚举,它可以是
- 如果我在默认构造函数中放了一个参数,但给了这个参数一个默认值,它还是一个默认构造函数吗
- 为什么在c++中给typename模板参数一个默认值0 ?