C++ 可变模板与新算法

C++ 可变模板与新算法,c++,c++11,variadic-templates,C++,C++11,Variadic Templates,我有一个类模板: 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)...); } }; 如何以这种方式将可变模板与新模板一起使用?正确的语法

我有一个类模板:

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)...);
  }
};
如何以这种方式将可变模板与新模板一起使用?正确的语法是什么

编辑:我想我的问题不是很清楚。我想要的是:

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.

也许您希望在std::vector中包含一个元组?不确定这是否是您想要的,但这至少在我的G++4.6.1:D上编译

#include <vector>
#include <utility>
#include <functional>
#include <string>

template<class... T>
class Test {
  std::vector<std::tuple<T*...>> test_cases;
public:
  Test() {
    // Here, for each T an instance should be added to test_cases.
    test_cases.push_back(std::tuple<T*...>((new T)...));
  }
};

int main()
{
   Test<int, float> foo;
   Test<std::string, double> bar;
}

我突然想到,你想要任何类型的动态向量,尽管我自己看起来不太像,但我的一个朋友告诉我,boost库中显然有类似的东西,而不是模板向量

模板向量基本上是一个向量,它可以采用任何一种定义的类型,要么是所有整数,要么是所有双精度,要么是所有浮点值,但不是整数和双精度以及浮点值

传统上没有这样的类的原因是因为每个项在内存中占用不同的块大小一个char是一个字节,一个int可以是4个字节等等,并且在查找时需要额外的资源才能知道正常存储是连续的。。。向量是什么,假设它基本上是一个数组


如果你想建立你自己的,我试过了,你看到的是void*指针,动态内存分配,还有一大堆与类型转换有关的麻烦事我不知道有什么自动方法可以在幕后正确地键入一个项目,但是其他人可能可以插手。

包扩展只能在特定数量的情况下发生,并且不适用于任意表达式或语句。但是,由于其中一种情况是列表初始化,并且操作顺序是为列表初始化语法的大括号初始值设定项定义的,因此始终可以扩展任意语句。也就是说:

typedef std::initializer_list<int> expand;
expand { ( test_cases.push_back(new T), void(), 0 )... };
您可以实现这一点,但这有点迂回,因为您直接编写表达式。您需要为可变模板参数列表中的每个参数调用push_一次

你是如何做到这一点的?那么,通过为每个模板参数调用一次递归函数:

template <typename Base, typename T1, typename T2, typename... T>
void fill(std::vector<Base*>& vec) {
    vec.push_back(new T1);
    fill<Base, T2, T...>(vec);
}

template <typename Base, typename T1>
void fill(std::vector<Base*>& vec) {
    vec.push_back(new T1);
}
vector::push_back需要一个参数,因此无法在函数调用中展开变量模板。 此外,我还为所有其他类派生的基类添加了一个模板参数

这里有一件事


请注意,在这种特殊情况下,您可以通过编写如下构造函数来使用vector的初始值设定项列表支持

Test()
:test_cases{ new T ... }
{ }
或者,如果出于任何原因不能使用构造函数初始值设定项,则使用赋值

Test() {
  test_cases = { new T ... };
}

性病:病媒试验病例;看起来很奇怪,因为T不止一种类型。@awoodland你说得对。谢谢你发现这个。事实上,每个T都是TestCase的一个子类,这就是我使用指针的原因。我会改变这个。你可以试试测试用例。推回新的T@Kerrer SB:当我这样做时,我得到了这个错误:预期';'在表达式之后,请注意:表达式包含未展开的参数包“T”。@WTP您新添加的示例实际上非常糟糕,因为它不起作用,或者仅当使用向量时:int、double和char不共享公共基类。是的,很好。。。修好了。他在摆弄如何编译它,却没有想到显而易见的:OP想要的是完全可能的。注意,他显式地使用了指针向量。在他的例子中,如果所有类型都有一个共同的基类TestCase,这就允许多态性发生。从好的方面来说,你可以期望编译器对其进行优化,不是吗?@bitmask我不确定你所说的“优化”是什么意思。由于模板在编译时被完全解析,这将在编译时被完全解析。如果您提到内联,那么是的,“递归”填充调用将完全内联。我写了一个与此几乎相同的答案,直到现在都没有注意到你已经有了它。我更改了我的答案,不再重复你现在所说的内容:。但是你忘记了exp,void,0的参数。正如现在一样,尝试展开文本0时会出错。
fill<TestCase, T...>(test_cases);
struct base{};
struct d0 : base{};
struct d1 : base{};
struct d2 : base{};

#include <vector>

// termination condition for helper function
template <class T>
void add(std::vector<T*>&) { 
}

// helper function
template <class T, class Head, class... Tail>
void add(std::vector<T*>& v) { 
       v.push_back(new Head()); 
       add<T, Tail...>(v);
}

template <class T, class ... U>
class test
{
    std::vector<T*> vec;
public:
    test() {
       add<T, U...>(vec);      
    }
};

int main() 
{
    test<base, d0,d1,d2> t;
}
Test()
:test_cases{ new T ... }
{ }
Test() {
  test_cases = { new T ... };
}