我有这种类型:
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());
我也有这个类(class)模板:
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)...) {}
};
我想围绕
container
产生的对象构造一个mk_immobile()
,并使用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
实际上并不完美转发-prvalue不会作为prvalue转发。 (这对我来说很有意义;我认为这样做不可能。)我可以通过将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
。 最佳答案
你虐待 Actor
template<typename F>
struct initializer
{
F f;
template<typename T>
operator T()
{
return f();
}
};
template<typename F>
initializer(F&&) -> initializer<F>;
并用作
container<immobile> c{initializer{[]{
return mk_immobile();
}}};