[英]How to guarantee copy elision with std::variant?
I have this type: 我有这种类型:
struct immobile {
// other stuff omitted
immobile(immobile&) = delete;
immobile(immobile&&) = delete;
};
immobile mk_immobile();
// e.g. this compiles
// mk_immobile() is a prvalue and i is its result object
immobile i(mk_immobile());
I also have this class template: 我也有这个类模板:
template<typename T>
struct container {
std::variant<T, other_stuff> var;
template<typename... Args>
container(Args&&... args)
: var(std::in_place_index<0>, std::forward<Args>(args)...) {}
};
I want to construct a container
around the object produced by mk_immobile()
, with the immobile
object used to initialize one of the variants of var
. 我想建立一个
container
周围所产生的对象mk_immobile()
与immobile
用于初始化的变体的一个目的var
。
container<immobile> c(mk_immobile());
However, this does not work. 但是,这不起作用。 For one,
std::variant
's constructor wants std::is_constructible_v<immobile, immobile>
, which doesn't hold. 首先,
std::variant
的构造函数需要std::is_constructible_v<immobile, immobile>
,它不成立。 Worse, even this simplified version fails: 更糟糕的是,即使这个简化版本也失败了
template<typename T>
struct demonstration {
T t;
template<typename... Args>
demonstration(Args&&... args) : t(std::forward<Args>(args)...) {}
};
demonstration<immobile> d(mk_immobile());
Which seems to imply that std::forward
does not, in fact, perfectly forward—prvalues do not forward as prvalues. 这似乎暗示
std::forward
实际上并不是完美的前锋 - prvalues不会作为prvalues前进。 (This makes sense to me; I don't think doing that would be possible.) I can make demonstration
work by changing it to this: (这对我来说很有意义;我不认为这样做是可能的。)我可以通过改变它来进行
demonstration
工作:
template<typename T>
struct demonstration {
T t;
template<typename F>
demonstration(F&& f) : t(std::forward<F>(f)()) {}
};
demonstration<immobile> d([] { return mk_immobile(); });
But I do not see a way to change container
in a similar manner. 但我没有看到以类似方式更换
container
的方法。 How do I change container
so that it can construct a std::variant
(or other tagged union) out of a prvalue? 如何更改
container
以便它可以从prvalue构造一个std::variant
(或其他标记的联合)? I can change container
but cannot change immobile
. 我可以更换
container
但不能改变immobile
。
You abuse casts 你滥用演员
template<typename F>
struct initializer
{
F f;
template<typename T>
operator T()
{
return f();
}
};
template<typename F>
initializer(F&&) -> initializer<F>;
And use as 并用作
container<immobile> c{initializer{[]{
return mk_immobile();
}}};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.