参数包扩展有问题
Having trouble with parameter pack expansion
我正在处理 class 模板,其中模板本身不是可变类型,但是 class 的构造函数是。我试图获取参数包的所有值并将它们存储到一个向量中,但我似乎无法编译代码,我不断收到编译器错误消息,指出必须在此上下文中扩展参数包,并且我不确定正确的语法是什么。这是我的 class:
template<class T>
class TableRow {
private:
std::string id_;
std::vector<T> values_;
public:
template<class T, class... Params>
TableRow( const std::string& id, T firstVal, Params... valuePack ) :
id_(id) {
values.push_back( firstVal );
for ( auto t : (valuePack...) ) { // Compiler error here
values_.push_back( t );
}
}
// ... other methods
};
除了让它正确编译之外,我唯一关心的是有没有办法确保所有 Params
都是 T
类型?
换句话说,这就是我在实例化此 class
时想要实现的目标
TableRow<int> trInt1( "Row1", 1, 2, 3, 4, 5 );
TableRow<int> trInt2( "Row2", 6, 7, 8, 9, 10 );
TableRow<float> trFloat1( "Row1", 2.2f, 3.3f, 4.4f );
TableRow<float> trFloat2( "Row1", 4.5f, 7.9f );
// In the above examples the first two rows are of the same length
// meaning their vector sizes are equal in length therefor they are
// compatible to fit inside of single table. The table is
// a class template that takes type <T> the same type as the RowTable<T>.
// The Table<T>'s constructor accepts a TableRow<T>.
// With the next two examples of the floats they are both indeed table rows
// but they can not fit into the same table since they are of different length
// The following is what I do not want:
TableRow<char> row( "row1", 'a', 3, 5, 2.4f, someClass );
// This is not allowed, all data types from the 2nd parameter on
// must all be of the same type!
编辑
我采纳了 liliscent
的建议并将 class 模板的声明更改为如下所示:
template<class T>
class TableRow {
private:
std::string id_;
std::vector<T> values_;
public:
template<class... Params>
TableRow( std::string id, Params&&... valuePack ) :
id_( id ),
values_ { std::forward<Params>( valuePack )... }
{}
std::string getID() const {
return id_;
}
std::vector<T> getValues() const {
return values_;
}
std::size_t getSize() const {
return values_.size();
}
};
现在可以编译了...感谢您的帮助,因为我现在可以继续编写其余部分 class。晚些时候;一旦我的两个 classes 一起工作,如果一切顺利,我会接受他们的回答。
你的编译失败只是一个语法错误,你不能以这种方式使用基于范围的for循环。参见 http://en.cppreference.com/w/cpp/language/range-for。
为了解决这个问题,您可以使用 std::vector
的基于 std::initializer_list
的构造函数,它确保所有值自动具有相同的类型。
template<class... Args>
TableRow( const std::string& id, Args&&... valuePack )
: id_(id)
, values_{ std::forward<Args>(valuePack)... }
{}
而且我认为如果您想进一步固定 TableRow
中的元素数量,您应该使用 std::array
。然后你可以有另一个模板参数 int N
在编译时检查某些行是否可以放入 table.
语法错误的修复:
template<class T, class... Params>
TableRow( const std::string& id, T firstVal, Params... valuePack ) :
id_(id) {
values.push_back( firstVal );
for ( auto t : { valuePack...} ) { // or { static_cast<T>(valuePack) ...}
values_.push_back( t );
}
}
我建议直接拿vector
:
TableRow(const std::string& id, std::vector<T> values) :
id_(id), values(std::move(values)) {}
用法略有不同:
TableRow<int> trInt1( "Row1", { 1, 2, 3, 4, 5 });
TableRow<int> trInt2( "Row2", { 6, 7, 8, 9, 10 });
TableRow<float> trFloat1( "Row1", { 2.2f, 3.3f, 4.4f });
TableRow<float> trFloat2( "Row1", { 4.5f, 7.9f });
我正在处理 class 模板,其中模板本身不是可变类型,但是 class 的构造函数是。我试图获取参数包的所有值并将它们存储到一个向量中,但我似乎无法编译代码,我不断收到编译器错误消息,指出必须在此上下文中扩展参数包,并且我不确定正确的语法是什么。这是我的 class:
template<class T>
class TableRow {
private:
std::string id_;
std::vector<T> values_;
public:
template<class T, class... Params>
TableRow( const std::string& id, T firstVal, Params... valuePack ) :
id_(id) {
values.push_back( firstVal );
for ( auto t : (valuePack...) ) { // Compiler error here
values_.push_back( t );
}
}
// ... other methods
};
除了让它正确编译之外,我唯一关心的是有没有办法确保所有 Params
都是 T
类型?
换句话说,这就是我在实例化此 class
时想要实现的目标TableRow<int> trInt1( "Row1", 1, 2, 3, 4, 5 );
TableRow<int> trInt2( "Row2", 6, 7, 8, 9, 10 );
TableRow<float> trFloat1( "Row1", 2.2f, 3.3f, 4.4f );
TableRow<float> trFloat2( "Row1", 4.5f, 7.9f );
// In the above examples the first two rows are of the same length
// meaning their vector sizes are equal in length therefor they are
// compatible to fit inside of single table. The table is
// a class template that takes type <T> the same type as the RowTable<T>.
// The Table<T>'s constructor accepts a TableRow<T>.
// With the next two examples of the floats they are both indeed table rows
// but they can not fit into the same table since they are of different length
// The following is what I do not want:
TableRow<char> row( "row1", 'a', 3, 5, 2.4f, someClass );
// This is not allowed, all data types from the 2nd parameter on
// must all be of the same type!
编辑
我采纳了 liliscent
的建议并将 class 模板的声明更改为如下所示:
template<class T>
class TableRow {
private:
std::string id_;
std::vector<T> values_;
public:
template<class... Params>
TableRow( std::string id, Params&&... valuePack ) :
id_( id ),
values_ { std::forward<Params>( valuePack )... }
{}
std::string getID() const {
return id_;
}
std::vector<T> getValues() const {
return values_;
}
std::size_t getSize() const {
return values_.size();
}
};
现在可以编译了...感谢您的帮助,因为我现在可以继续编写其余部分 class。晚些时候;一旦我的两个 classes 一起工作,如果一切顺利,我会接受他们的回答。
你的编译失败只是一个语法错误,你不能以这种方式使用基于范围的for循环。参见 http://en.cppreference.com/w/cpp/language/range-for。
为了解决这个问题,您可以使用 std::vector
的基于 std::initializer_list
的构造函数,它确保所有值自动具有相同的类型。
template<class... Args>
TableRow( const std::string& id, Args&&... valuePack )
: id_(id)
, values_{ std::forward<Args>(valuePack)... }
{}
而且我认为如果您想进一步固定 TableRow
中的元素数量,您应该使用 std::array
。然后你可以有另一个模板参数 int N
在编译时检查某些行是否可以放入 table.
语法错误的修复:
template<class T, class... Params>
TableRow( const std::string& id, T firstVal, Params... valuePack ) :
id_(id) {
values.push_back( firstVal );
for ( auto t : { valuePack...} ) { // or { static_cast<T>(valuePack) ...}
values_.push_back( t );
}
}
我建议直接拿vector
:
TableRow(const std::string& id, std::vector<T> values) :
id_(id), values(std::move(values)) {}
用法略有不同:
TableRow<int> trInt1( "Row1", { 1, 2, 3, 4, 5 });
TableRow<int> trInt2( "Row2", { 6, 7, 8, 9, 10 });
TableRow<float> trFloat1( "Row1", { 2.2f, 3.3f, 4.4f });
TableRow<float> trFloat2( "Row1", { 4.5f, 7.9f });