使用确定类型转发引用行为
Forwarding reference behavior with definite types
假设我有一个模板类
template <typename T> class foo;
template <typename... Args>
struct foo<std::tuple<Args...>> {
std::tuple<Args...> t;
foo(Args&&... args): t{std::forward<Args>(args)...} { }
};
我知道在这种情况下Args&&...
是右值引用,我可以写得很好std::move
而不是std::forward
。
我也可以有一个带有左值引用的构造函数,就像这样
foo(const Args&... args): t{args...} { }
问题是是否有可能获得与转发引用相同的行为,但对于确定的类型?我想要这个的原因是这样我就可以使用这样的语法
foo bar({. . .}, {. . .}, . . ., {. . .});
如果我定义foo(Args&&... args)
构造函数,这有效,但不允许混合方案,其中我想使用大括号括起来的初始值设定项列表初始化一些成员元组元素,并从预先存在的对象实例复制其他元素。
当然;有一个花哨而简单的方法。
我将在下面详细介绍的奇特方式。 首先是简单的方法:按值取。
template <typename... Args>
struct foo<std::tuple<Args...>> {
std::tuple<Args...> t;
foo(Args... args): t{std::forward<Args>(args)...} { }
};
真的,就这样做。 如果Args
包含引用,则 Forward 用于执行正确的操作。
按价值获取比完美转发增加了一个动作,但成倍地减少了对过载的要求。
这是花哨的方式。 我们键入擦除结构:
template<class T>
struct make_it {
using maker=T(*)(void*);
maker f;
void* args;
// make from move
make_it( T&& t ):
f([](void* pvoid)->T{
return std::move(*static_cast<T*>(pvoid));
}),
args(std::addressof(t))
{}
// make from copy
make_it( T const& t ):
f([](void* pvoid)->T{
return *(T const*)(pvoid);
}),
args(std::addressof(t))
{}
operator T()&&{return std::move(*this)();}
T operator()()&&{ return f(args); }
};
此类型通过复制或移动擦除构造。
template <typename... Args>
struct foo<std::tuple<Args...>> {
std::tuple<Args...> t;
foo(make_it<Args>... args): t{std::move(args)()...} { }
};
它不是完全透明的,但它是我所能得到的尽可能接近。
需要双{{}}
而不是单。 这是一个用户定义的转换,因此不会隐式执行另一个转换。 我们可以添加一个通用 ctor:">
// make from universal
template<class U>
make_it( U&& u ):
f([](void* pvoid)->T{
return std::forward<U>(*(U*)(pvoid));
}),
args(std::addressof(u))
{}
如果我们添加一个 sfinae 奶嘴,U&&
可以用来隐式构造T
,效果会更好。
它有一些优点,但与仅按价值获取相比,它们微不足道。 例如,在C++17中,在某些情况下,非移动类型可以完全正向构造。
相关文章:
- 正在折叠转发引用
- 如何在模板中转发右值和左值引用
- 通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
- C++ 何时使用常量引用而不是转发引用
- 为什么转发声明的好友类不能在类中引用?
- C++完美转发:如何避免悬空引用
- C++:通用(转发)引用中不允许常量
- 模板模板参数和转发引用
- 常量转发引用给出错误 C2440:"正在初始化":无法从"常量标准::字符串"转换为"常量标准::字符串 &&"
- 具有右值引用,而不是使用可变参数模板转发引用
- 自定义类型转换运算符在转发引用上调用时不起作用(当对象按值传递时有效)
- 如何从常量引用或通过转发模板临时构造对象
- 结构化绑定和转发引用是否混合良好?
- 如何声明接受转发引用并返回引用或副本的函数模板
- 间接转发引用
- 为什么调用转发引用构造函数而不是复制构造函数?
- 为什么 std::get 没有一个接受转发引用的签名
- 有没有办法在不引用其模板类型的情况下转发声明指向类的指针
- c++重新评估引用转发性能
- 右值引用转发错误