我有这种类型:
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)...) {}
};
我想围绕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
实际上并不完美地转发-pr值不会作为pr值转发。 (这对我来说很有意义;我认为这样做不可能。)我可以通过将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
。
答案 0 :(得分:1)
您滥用演员表
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();
}}};