可变参数模板和新的
我有这样的类模板:
template<class... T>
class Test {
std::vector<TestCase*> test_cases;
public:
Test() {
// Here, for each T an instance should be added to test_cases.
test_cases.push_back((new T)...);
}
};
这对于一个模板参数来说效果很好,但是对于多个参数我收到此错误:
error: too many arguments to function call, expected 1, have 2
如何以这种方式将可变参数模板与 new
一起使用?正确的语法是什么?
编辑:我认为我的问题不太清楚。我想要的是这样的:
Test<TestCase1, TestCase2, TestCase3>;
// The constructor will then be:
test_cases.push_back(new TestCase1);
test_cases.push_back(new TestCase2);
test_cases.push_back(new TestCase3);
我的编译器是 clang 163.7.1,带有此标志:-std=c++0x
。
I have this class template:
template<class... T>
class Test {
std::vector<TestCase*> test_cases;
public:
Test() {
// Here, for each T an instance should be added to test_cases.
test_cases.push_back((new T)...);
}
};
This works fine for one template argument, but for multiple arguments I get this error:
error: too many arguments to function call, expected 1, have 2
How can I use variadic templates with new
this way? What is the correct syntax?
EDIT: I think my question wasn't quite clear. What I want is this:
Test<TestCase1, TestCase2, TestCase3>;
// The constructor will then be:
test_cases.push_back(new TestCase1);
test_cases.push_back(new TestCase2);
test_cases.push_back(new TestCase3);
My compiler is clang 163.7.1 with this flag: -std=c++0x
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
vector::push_back
需要一个参数,因此您无法在函数调用中扩展可变参数模板。我还为基类(所有其他类派生自该基类)添加了一个模板参数。
这是编译的内容。
vector::push_back
expects one parameter so you can't expand the variadic template in the function call.Also I added a template parameter for the base class (from which all other classes derive).
Here's something that compiles.
您可以完成此任务,但由于您直接编写表达式,因此有点迂回。您需要为可变参数模板参数列表中的每个参数调用一次
push_back
。你如何实现这一目标?好吧,通过为每个模板参数调用一次递归函数:
这里我们有两个
fill
函数的重载,一个带有可变参数模板参数列表,另一个没有 - 这是递归基本情况。只要仍然至少有两个模板参数,就会调用第一个版本。如果只剩下一个参数,则调用第二个参数。在构造函数中这样调用它:
You can accomplish this, but it’s a bit roundabout since you write the expression directly. You need to call
push_back
once for each argument in the variadic template argument list.How do you achieve this? Well, by calling a recursive function once for each template argument:
Here we have two overloads of the
fill
function, one with a variadic template argument list and one without – this is the recursion base case. As long as there are still at least two template arguments, the first version gets called. If there is only a single argument left, the second argument is called instead.Call it like this in the constructor:
包扩展只能在选定的几种情况下发生,并且不适用于任意表达式或语句。但是,由于其中一种情况是列表初始化,并且由于操作顺序是为列表初始化语法的大括号初始值设定项定义的,因此始终可以扩展任意语句。也就是说:
void()
技巧是抑制对重载运算符
的任何调用。此处完全不相关,但我已将其包含在内,因为在重构宏中的功能时它可能很有用:Pack expansion can only happen in a select number of situations and doesn't work for arbitrary expressions or statements. However, since one of those situation is list-initialization and since the order of operations is defined for the brace initializers of list-initialization syntax, it's always possible to expand an arbitrary statement. To wit:
The
void()
trick is to suppress any invocation of an overloadedoperator,
. Completely irrelevant here but I have included it since it may be useful when refactoring the functionality in a macro:相关说明,在这种特殊情况下,您可以通过如下编写构造函数来使用向量的
initializer_list
支持,或者如果由于任何原因无法使用构造函数初始值设定项,则可以使用赋值
On a related note, in this particular case you can use vector's
initializer_list
support by writing the constructor as followsOr by using assignment if for any reason you can't use constructor initializers
也许您想要 std::vector 中的元组?不确定这是否是您想要的,但这至少可以在我的 G++ 4.6.1 上编译:D
Maybe you want a tuple inside your std::vector? Not sure if this is what you intended, but this compiles at least on my G++ 4.6.1 :D
我突然想到你想要一个 any 类型的动态向量(虽然不是我个人看的,但一位朋友告诉我,boost 库中显然有类似的东西),而不是模板向量。
模板向量基本上是一个可以采用任何一个定义类型的向量(所有整数,或所有双精度数,或所有浮点数,但不是整数、双精度数和浮点数)。
传统上没有这样的类的原因是因为每个项目在内存中占用不同的块大小(char 是一个字节,int 可以是 4 个字节等),并且在查找时需要额外的资源知道会发生什么(正常存储是连续的......向量是什么,假设它“基本上”是一个数组)。
如果你想构建自己的(我尝试过),你会看到 void * 指针、动态内存分配和涉及类型转换的一系列令人头疼的问题(我不知道有任何自动化方法可以在幕后正确类型转换项目) ,但其他人也许能够参与)。
It strikes me you want a dynamic vector of any type (although not personally looking myself, I was told by a friend there was apparently something like this in the boost library), as opposed to a template vector.
A template vector is basically a vector that can assume any of one defined type (either all ints, or all doubles, or all floats but not ints and doubles and floats).
The reason there isn't a class like this conventionally is because each item takes up a different block size in memory (a char is a byte, an int could be 4 bytes etc etc), and it would take additional resources on look-up to know what to expect (normal storage is contiguous... which a vector is, given it is 'basically' an array).
If you're looking to build your own (I tried), you're looking at void * pointers, dynamic memory allocation and a whole host of headaches involving typecasting (I am unaware of any automated method to correctly typecast an item behind the scenes, but others might be able to chip in).