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:不知道为什么我从来没有见过你