C++ 在向量中插入可变参数列表?

C++ 在向量中插入可变参数列表?,c++,c++11,variadic-functions,C++,C++11,Variadic Functions,如果这个问题已经得到了回答,请原谅我,因为我找不到它 基本上,我有一个对象,需要在它的构造函数中获取一个可变参数列表,并将参数存储在一个向量中。如何从变量构造函数的参数初始化向量 class GenericNode { public: GenericNode(GenericNode*... inputs) { /* Something like... */ // inputs_.push_back(inputs)...; } private:

如果这个问题已经得到了回答,请原谅我,因为我找不到它

基本上,我有一个对象,需要在它的构造函数中获取一个可变参数列表,并将参数存储在一个向量中。如何从变量构造函数的参数初始化向量

class GenericNode {
public:
    GenericNode(GenericNode*... inputs) {
            /* Something like... */
        // inputs_.push_back(inputs)...;
}
private:
    std::vector<GenericNode*> inputs_;
};
类GenericNode{
公众:
GenericNode(GenericNode*…输入){
/*类似于*/
//输入。推回(输入)。。。;
}
私人:
std::矢量输入;
};

除非变量参数列表是一个模板,否则不能使用变量参数列表。如上所述,可以使用如下初始值设定项列表:

class GenericNode {
public:
    GenericNode(std::initializer_list<GenericNode*> inputs) : inputs_(inputs)
    {
    }
private:
    std::vector<GenericNode*> inputs_;
};

template <class ... T>
GenericNode* foo(T ... t)
{
    return new GenericNode({t...});
}
类GenericNode{
公众:
GenericNode(std::initializer\u列表输入):输入(输入)
{
}
私人:
std::矢量输入;
};
模板
GenericNode*foo(T…T)
{
返回新的GenericNode({t..});
}
最好使用初始值设定项列表

#include <initializer_list>
#include <vector>
class GenericNode {
public:
    GenericNode(std::initializer_list<GenericNode*> inputs) 
        :inputs_(inputs) {} //well that's easy
private:
    std::vector<GenericNode*> inputs_;
};
int main() {
    GenericNode* ptr;
    GenericNode node{ptr, ptr, ptr, ptr};
} //compilation at http://stacked-crooked.com/view?id=88ebac6a4490915fc4bc608765ba2b6c
template<class T>
using Alias = T;

class GenericNode {
public:
    template<class ...Ts>
    GenericNode(Ts... inputs) { //SFINAE might be appropriate
         using ptr = GenericNode*;
         Alias<char[]>{( //first part of magic unpacker
             inputs_.push_back(ptr(inputs))
             ,'0')...,'0'}; //second part of magic unpacker
    }
private:
    std::vector<GenericNode*> inputs_;
};
int main() {
    GenericNode* ptr;
    GenericNode node(ptr, ptr, ptr, ptr);
} //compilation at http://stacked-crooked.com/view?id=57c533692166fb222adf5f837891e1f9
//thanks to R. Martinho Fernandes for helping me get it to compile
#包括
#包括
类GenericNode{
公众:
GenericNode(std::初始值设定项\u列表输入)
:inputs(inputs){}//那很容易
私人:
std::矢量输入;
};
int main(){
通用节点*ptr;
GenericNode节点{ptr,ptr,ptr,ptr};
}//编译于http://stacked-crooked.com/view?id=88ebac6a4490915fc4bc608765ba2b6c
使用C++11最接近您已有的是使用向量的初始值设定项列表:

    template<class ...Ts>
    GenericNode(Ts... inputs) 
        :inputs_{inputs...} {} //well that's easy too
    //compilation at http://stacked-crooked.com/view?id=2f7514b33401c51d33677bbff358f8ae
模板
通用节点(Ts…输入)
:inputs{inputs…}{}//这也很容易
//汇编于http://stacked-crooked.com/view?id=2f7514b33401c51d33677bbff358f8ae
这是一个C++11版本,根本没有初始值设定项列表。它丑陋、复杂,需要许多编译器缺少的功能。使用初始值设定项列表

#include <initializer_list>
#include <vector>
class GenericNode {
public:
    GenericNode(std::initializer_list<GenericNode*> inputs) 
        :inputs_(inputs) {} //well that's easy
private:
    std::vector<GenericNode*> inputs_;
};
int main() {
    GenericNode* ptr;
    GenericNode node{ptr, ptr, ptr, ptr};
} //compilation at http://stacked-crooked.com/view?id=88ebac6a4490915fc4bc608765ba2b6c
template<class T>
using Alias = T;

class GenericNode {
public:
    template<class ...Ts>
    GenericNode(Ts... inputs) { //SFINAE might be appropriate
         using ptr = GenericNode*;
         Alias<char[]>{( //first part of magic unpacker
             inputs_.push_back(ptr(inputs))
             ,'0')...,'0'}; //second part of magic unpacker
    }
private:
    std::vector<GenericNode*> inputs_;
};
int main() {
    GenericNode* ptr;
    GenericNode node(ptr, ptr, ptr, ptr);
} //compilation at http://stacked-crooked.com/view?id=57c533692166fb222adf5f837891e1f9
//thanks to R. Martinho Fernandes for helping me get it to compile
模板
使用别名=T;
类GenericNode{
公众:
模板
GenericNode(Ts…输入){//SFINAE可能是合适的
使用ptr=GenericNode*;
别名{(//magic unpacker的第一部分
输入。推回(ptr(输入))
,'0')…,'0'};//magic unpacker的第二部分
}
私人:
std::矢量输入;
};
int main(){
通用节点*ptr;
通用节点(ptr、ptr、ptr、ptr);
}//编译于http://stacked-crooked.com/view?id=57c533692166fb222adf5f837891e1f9
//感谢R.Martinho Fernandes帮助我编译
与所有事情无关,我不知道这些人是否拥有指针。如果是,请改用
std::unique_ptr

    // inputs_.push_back(inputs)...;
这不起作用,因为您不能将参数包作为语句展开,只能在某些上下文中展开,例如函数参数列表或初始值设定项列表

此外,您的构造函数签名是错误的,如果您试图编写可变模板,它需要是一个模板

正确编写构造函数签名后,答案很简单,只需使用包扩展构造向量即可:

#include <vector>

class GenericNode
{
public:
  template<typename... T>
    GenericNode(T*... inputs) : inputs_{ inputs... }
    { }
private:
    std::vector<GenericNode*> inputs_;
};
但是酷孩子使用成员初始值设定项,而不是构造函数体中的赋值。)

此解决方案的缺点是,模板构造函数接受任何类型的指针参数,但如果参数不能转换为
GenericNode*
,则在尝试构造向量时会出现错误。您可以将模板约束为仅接受
GenericNode
指针,但如果您按照其他答案的建议执行,并使构造函数采用
std::initializer\u列表,那么您就不需要任何丑陋的
启用\u if
SFINAE技巧。

另一种方法:

#include <iostream>
#include <vector>

using std::vector;

template <typename T>
void variadic_vector_emplace(vector<T>&) {}

template <typename T, typename First, typename... Args>
void variadic_vector_emplace(vector<T>& v, First&& first, Args&&... args)
{
    v.emplace_back(std::forward<First>(first));
    variadic_vector_emplace(v, std::forward<Args>(args)...);
}

struct my_struct
{
    template <typename... Args>
    my_struct(Args&&... args)
    {
        variadic_vector_emplace(_data, std::forward<Args>(args)...);
    }

    vector<int>& data() { return _data; }

private:
  vector<int> _data;
};


int main()
{
    my_struct my(5, 6, 7, 8);

    for(int i : my.data())
      std::cout << i << std::endl;
}
#包括
#包括
使用std::vector;
模板
无效变量向量(向量&){}
模板
无效变量向量模板(向量&v、第一和第一、参数和…参数)
{
v、 向后(标准:向前(第一));
变量向量布设(v,标准::正向(args)…);
}
结构我的结构
{
模板
我的结构(Args&&…Args)
{
变量向量安放(_数据,标准::正向(args)…);
}
向量和数据(){return_data;}
私人:
矢量数据;
};
int main()
{
我的结构我的(5,6,7,8);
for(int i:my.data())
std::cout
类Blob
{
std::vector_v;
公众:
模板
Blob(Args&&…Args)
:_v(标准::转发(参数)…)
{  }
};
内部主(空)
{
const char*shapes[3]={“圆”、“三角形”、“正方形”};
BLOBB1(5,“C++真理”);
Blob b2(形状,形状+3);
}
来自C++11 Truths的示例看起来足够简单…;)
这不是一个完整的解决方案,但可能会给您一些想法。

我最近编写了以下函数,其中包含一个字符串 {1} ,{2},{3}…并替换参数列表。我遇到了相同的问题,直到我决定让编译器使用auto关键字自行解决

#include <string>
#include <vector>

using std::string;
using std::vector;

template<typename S, typename... Args>
string interpolate( const S& orig , const Args&... args)
{
   string out(orig);

   auto va = {args...};
   vector<string> v{va};

   size_t i = 1;

   for( string s: v)
    {
      string is = std::to_string(i);
      string t = "{" +  is + "}";
      try
         {
           auto pos = out.find(t);
           if(pos != out.npos) 
              {
                 out.erase(pos, t.length());
                 out.insert( pos, s); 
              }                  
           i++;
         }
    catch( std::exception& e)
       {
          std::cerr << e.what() << std::endl;
       }
     } // for

   return out;
 }
#包括
#包括
使用std::string;
使用std::vector;
模板
字符串插值(常量S&orig、常量参数和…参数)
{
串出(原);
自动va={args…};
向量v{va};
尺寸i=1;
用于(字符串s:v)
{
字符串is=std::to_字符串(i);
字符串t=“{”+是+“}”;
尝试
{
自动位置=out.find(t);
如果(pos!=out.npos)
{
删除(位置,t.长度());
向外插入(位置s);
}                  
i++;
}
捕获(标准::异常&e)
{

std::cerr在您的示例中有一些无效语法。您具体想问什么?使用
std::initializer\u list
。抱歉。为了澄清,我如何使用参数列表填充std::vector?@MooingDuck,我将研究std::initializer\u list。谢谢。为什么您有helper函数?@MooingDuck只是为了展示variadi的使用c模板参数不能
template GenericNode(t*…inputs):inputs\u{inputs…}{}
更接近他已经拥有的?不过我还是会选择
std::initializer\u list
。@JonathanWakely:不知道为什么我从来没有见过你