c++ 模板中的多个类型名参数?(可变参数模板)
Multiple typename arguments in c++ template? (variadic templates)
如何在 c++ 模板中有多个类型名参数?
#ifndef _CALL_TEMP_H
#define _CALL_TEMP_H
#include <string>
#include <iostream>
template <typename Sig>
class Foo;
template <typename A, typename B>
class Foo
{
public:
void output() {
std::cout << a_ << b_ << std::endl;
}
A a_;
B b_;
};
template <typename A, typename B, typename C>
class Foo
{
public:
void output() {
std::cout << a_ << b_ << c_ << std::endl;
}
A a_;
B b_;
C c_;
};
#endif
用法:
int main()
{
Foo<int ,int> doubleint;
doubleint.a_ = 1;
doubleint.b_ = 2;
doubleint.output();
// Foo<int , int , std::string> comp;
// comp.a_ = 1;
// comp.b_ = 2;
// comp.c_ = "haha";
// comp.output();
return 0;
}
但它不会编译。如何编译它?
只需声明一个带有可变参数模板的主模板,然后专门针对每个支持的模板参数数量。例如:
#ifndef CALL_TEMP_H
#define CALL_TEMP_H
#include <iostream>
template <typename...> class Foo;
template <typename A, typename B>
class Foo<A, B>
{
public:
void output() {
std::cout << a_ << b_ << 'n';
}
A a_;
B b_;
};
template <typename A, typename B, typename C>
class Foo<A, B, C>
{
public:
void output() {
std::cout << a_ << b_ << c_ << 'n';
}
A a_;
B b_;
C c_;
};
#endif
我不能使用 C++11 并且您想保留类似的符号,您需要使用模板默认参数模拟可变参数列表。这将隐式限制模板参数的数量,但由于您无论如何都要专门使用模板,因此此限制并不重要。
如果可以使用不同的表示法,您还可以使用看起来像函数声明的东西来实例化和专用化您的模板:
template <typename> class Foo;
template <typename A, typename B>
class Foo<void(A, B)> {
...
};
template <typename A, typename B, typename C>
class Foo<void(A, B, C)> {
...
};
...
Foo<void(int, int)> f2;
Foo<void(int, int, std::string)> f3;
表示法的更改是否可接受取决于您对类模板的使用。但是,如果没有 C++11,您将无法像可变参数模板那样获得理想的解决方案。
顺便说一句,不要过度使用std::endl
:使用'n'
表示行尾。如果您确实要刷新流,请使用 std::flush
.此外,_CALL_TEMP_H
是保留给标准C++库的名称,所有名称都以下划线开头,后跟大写字符:除非有明确的使用许可,否则不要在您自己的代码中使用这些名称(例如 保留__FILE__
和__LINE__
,但授予使用它们的明确许可)。
如果模板有多个版本,则必须专门化单个版本。 如果你想要不同数量的参数,那么诀窍是使用标签类说"这个参数不是参数",并将其作为默认参数。
在您的情况下,类似于以下内容(编译和测试):
#include <iostream>
// tag class indicating "no member in this place"
struct nothing {};
template <typename A, typename B, typename C = nothing> // <- note default arg.
class Foo;
template <typename A, typename B>
class Foo<A, B, nothing> // <- note specialization
{
public :
void output() {
std::cout << a_ << b_ << std::endl;
}
A a_;
B b_;
};
template <typename A, typename B, typename C>
class Foo
{
public :
void output() {
std::cout << a_ << b_ << c_ << std::endl;
}
A a_;
B b_;
C c_;
};
int main()
{
Foo<int, int> doubleint;
doubleint.a_ = 1;
doubleint.b_ = 2;
doubleint.output();
Foo<int, int, int> tripleint;
tripleint.a_ = 1;
tripleint.b_ = 2;
tripleint.c_ = 3;
tripleint.output();
}
请注意,这本质上是对boost::tuple<>/std::tuple<>的重新发明,您绝对应该阅读。
我认为您将专业化与重载相同的类名混淆了。不能创建具有多个模板参数的同名类。
它不会编译,因为您不能使用不同数量的模板参数多次定义同一个类。
如果您知道要支持的模板参数的最大数量,则可以使用部分专用化:
// main template
template <typename A, typename B = void, typename C = void>
struct Foo
{
void output() { std::cout << a_ << b_ << c_ << std::endl; }
A a_;
B b_;
C c_;
};
// Partial specialisation for two parameters
template <typename A, typename B>
struct Foo<A, B, void>
{
void output() { std::cout << a_ << b_ << c_ << std::endl; }
A a_;
B B_;
};
// Partial specialisation for one parameter
template <typename A>
struct Foo<A, void, void>
{
void output() { std::cout << a_ << std::endl; }
A a_;
};
如果您使用的是 C++11,另一种选择是使用可变参数模板。
- 在不传递参数数量且只有3个点的情况下,如何使用变差函数
- 如何使用可变参数模板强制转换每个变体类型
- 关于如何在具有单个参数的变体构造中选择替代方案?
- 调用参数排列不变函数 f(i++, i++)
- 参数归纳与标准::变体
- 模板化回调参数的逆变,如 C# 中的逆变
- 如何在没有参数包的情况下编写变差函数
- 通过具有嵌套类的工厂类获取多个变异类模板参数包
- 获取模板参数的成员变量值列表
- 保留短 lambda 用作函数的中间参数,使用 clang 格式保持不变
- 如何定义变体<x,y,z>提取模板参数的子类型
- 正确对齐内存模板,参数顺序不变
- 递归中不同参数类型的变元模板函数
- 通过函数指针传递给变差函数的参数会更改其值
- 提升预定义为带有参数的全局 lambda 的变体访问者
- 使用可变参数模板参数提升变体访问者
- boost ::变体 - 为什么模板参数比const字符串参数具有更高的优先级
- 将变参数包中的值加载到临时数组中
- 使用额外参数提升变体访客
- 正在将动态数组元素解析为参数?(变音符)