【发布时间】:2019-06-04 00:12:19
【问题描述】:
我有这种类型:
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());
我也有这个类模板:
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)...) {}
};
我想围绕mk_immobile() 生成的对象构造一个container,其中immobile 对象用于初始化var 的变体之一。
container<immobile> c(mk_immobile());
但是,这不起作用。一方面,std::variant 的构造函数需要std::is_constructible_v<immobile, immobile>,但它不成立。更糟糕的是,即使是这个简化版本也失败了:
template<typename T>
struct demonstration {
T t;
template<typename... Args>
demonstration(Args&&... args) : t(std::forward<Args>(args)...) {}
};
demonstration<immobile> d(mk_immobile());
这似乎暗示std::forward 实际上并不完全转发——prvalues 不会作为prvalues 转发。 (这对我来说很有意义;我认为这样做是不可能的。)我可以通过将 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(); });
但我看不到以类似方式更改 container 的方法。如何更改container 以便它可以从prvalue 构造std::variant(或其他标记的联合)?我可以更改container,但不能更改immobile。
【问题讨论】:
-
通过快速测试:gcc.godbolt.org/z/27cALe 似乎应该可以通过使用基于延迟回调的构造思想来实现一个按照您想要的方式运行的标记联合(我只是做了很多同一事物的更简单版本)
标签: c++ c++17 variant copy-elision