如何转发元组的值? std::get( move(tuple) ) 与 forward( std::get(tuple) )
How to forward the values of a tuple? std::get( move(tuple) ) vs. forward( std::get(tuple) )
假设您写了类似 "initializer" class 的内容,其中 存储了一组值 (包括引用)。然后使用这些值 来初始化给定类型 (例如通过 my_initializer.initialize<Foo>()
:
template<typename... Values>
struct Initializer{
std::tuple<Values...> values;
template<typename TypeToInitialize, std::size_t... Is>
TypeToInitialize initialize_implementation( std::index_sequence<Is...> ){
return { std::get<Is>( this->values )... };
}
template<typename TypeToInitialize>
TypeToInitialize initialize(){
return initialize_implementation( std::make_index_sequence<sizeof...(Values)>() );
}
};
非常简单的沙发。但是,现在我想为 rvalue 对象提供 initialize()
的重载,只要调用它的对象是 rvalue 并且调用 initialize<...>()
是对象被销毁前的最后一个动作。
如何转发元组的值?我应该选择哪个选项?
template<typename TypeToInitialize, std::size_t... Is>
TypeToInitialize initialize_move_implementation( std::index_sequence<Is...> )
{
// OPTION 1
return { std::forward<Values>( std::get<Is>( this->values ) )... };
// OPTION 2
return { std::get<Is>( std::move( this->values ) )... };
}
template<typename TypeToInitialize>
TypeToInitialize initialize() && {
return initialize_move_implementation<TypeToInitialize>( std::make_index_sequence<sizeof...(Values)>() );
}
template<typename TypeToInitialize>
TypeToInitialize initialize() && {
return std::make_from_tuple<TypeToInitialize>(this->values);
}
在内部,它会做类似的事情:
return T(std::get<I>(std::forward<Tuple>(t))...);
其中 I
是与原始示例中一样的索引序列。
如果存储的值是 T
或 T&&
类型(假设 T
是一个对象类型),两个选项都会产生 T&&
;如果存储的值是 T&
类型,两个选项都会产生 T&
,所以我认为这两个选项之间没有区别。我个人喜欢选项 2,因为 forward
通常与通用引用一起使用,将一个函数的参数转发给另一个函数,而这里你转发存储在 class 成员中的值,这可能有点混乱.
假设您写了类似 "initializer" class 的内容,其中 存储了一组值 (包括引用)。然后使用这些值 来初始化给定类型 (例如通过 my_initializer.initialize<Foo>()
:
template<typename... Values>
struct Initializer{
std::tuple<Values...> values;
template<typename TypeToInitialize, std::size_t... Is>
TypeToInitialize initialize_implementation( std::index_sequence<Is...> ){
return { std::get<Is>( this->values )... };
}
template<typename TypeToInitialize>
TypeToInitialize initialize(){
return initialize_implementation( std::make_index_sequence<sizeof...(Values)>() );
}
};
非常简单的沙发。但是,现在我想为 rvalue 对象提供 initialize()
的重载,只要调用它的对象是 rvalue 并且调用 initialize<...>()
是对象被销毁前的最后一个动作。
如何转发元组的值?我应该选择哪个选项?
template<typename TypeToInitialize, std::size_t... Is>
TypeToInitialize initialize_move_implementation( std::index_sequence<Is...> )
{
// OPTION 1
return { std::forward<Values>( std::get<Is>( this->values ) )... };
// OPTION 2
return { std::get<Is>( std::move( this->values ) )... };
}
template<typename TypeToInitialize>
TypeToInitialize initialize() && {
return initialize_move_implementation<TypeToInitialize>( std::make_index_sequence<sizeof...(Values)>() );
}
template<typename TypeToInitialize>
TypeToInitialize initialize() && {
return std::make_from_tuple<TypeToInitialize>(this->values);
}
在内部,它会做类似的事情:
return T(std::get<I>(std::forward<Tuple>(t))...);
其中 I
是与原始示例中一样的索引序列。
如果存储的值是 T
或 T&&
类型(假设 T
是一个对象类型),两个选项都会产生 T&&
;如果存储的值是 T&
类型,两个选项都会产生 T&
,所以我认为这两个选项之间没有区别。我个人喜欢选项 2,因为 forward
通常与通用引用一起使用,将一个函数的参数转发给另一个函数,而这里你转发存储在 class 成员中的值,这可能有点混乱.