C++ C++;一个引用的多次转发:先复制,然后移动
考虑以下代码,其中同一引用被转发两次到基类,并在基类中用于构造元组:C++ C++;一个引用的多次转发:先复制,然后移动,c++,c++11,operator-precedence,stdtuple,list-initialization,C++,C++11,Operator Precedence,Stdtuple,List Initialization,考虑以下代码,其中同一引用被转发两次到基类,并在基类中用于构造元组: template<typename ... Ts> struct Base { template<typename ... _Ts> Base(_Ts&& ... ts) : tup{std::forward<_Ts>(ts) ...} {} std::tuple <Ts ...> tup; }; template<typenam
template<typename ... Ts>
struct Base
{
template<typename ... _Ts>
Base(_Ts&& ... ts) : tup{std::forward<_Ts>(ts) ...} {}
std::tuple <Ts ...> tup;
};
template<typename T>
struct Derived : public Base<T, T>
{
template<typename _T>
Derived(_T&& t) : Base<T, T>{t, std::forward<_T>(t)} {}
};
这是。(gcc编译器在这方面显然有过一次bug,但已经两年了,应该不再是问题了。)
问题:
- 我在这里的实施或假设上哪里错了
- 如何修复上述代码,使其按预期运行:先复制,然后移动
- 我不确定对象初始化的操作顺序是否重要。由于完美的转发,在调用
std::tuple
构造函数之前,实际上不会进行复制或移动(即只传递左值引用和右值引用)。在这一点上,它取决于std::tuple
的实现细节
考虑是否使用了以下my\u tup
struct而不是std::tuple
:
template<typename T1, typename T2>
struct my_tup
{
template <typename A, typename B>
my_tup(A&& a, B&& b)
: t1(std::forward<A>(a)), t2(std::forward<B>(b))
{
}
T1 t1;
T2 t2;
};
模板
结构我的图
{
模板
我的房间(A&A,B&B)
:t1(std::forward)。但如果您有:
template<typename T1, typename T2>
struct my_tup
{
template <typename A, typename B>
my_tup(A&& a, B&& b)
: t2(std::forward<B>(b)), t1(std::forward<A>(a))
{
}
T2 t2;
T1 t1;
};
模板
结构我的图
{
模板
我的房间(A&A,B&B)
:t2(std::forward(b)),t1(std::forward)
很可能是由于变量模板的扩展方式,std::tuple
必须以从右到左的方式处理参数。我不确定这是依赖于实现还是在规范中指定的。您应该显式复制,否则您将传递一个引用,该引用稍后将由copy使用(但别名可能已被移动):
模板
结构派生:公共基
{
模板
派生(T&&T):基{T(T),std::forward(T)}{
};
任何以下划线开头,后跟大写字母的符号都是为实现保留的;将\u T
和\u Ts
更改为其他符号。很好的技巧:这应该有效(函数的参数在将结果传递给构造函数之前被调用,std::forward只是一个强制转换)谢谢,我想这就是答案。评估并不意味着构造。标准中相应的元组构造约束似乎不存在。另请参见其中的说明,元组构造中没有标准顺序。
template<typename T1, typename T2>
struct my_tup
{
template <typename A, typename B>
my_tup(A&& a, B&& b)
: t2(std::forward<B>(b)), t1(std::forward<A>(a))
{
}
T2 t2;
T1 t1;
};
template<typename U>
struct Derived : public Base<U, U>
{
template<typename T>
Derived(T&& t) : Base<U, U>{T(t), std::forward<T>(t)} {}
};