我有这种类型:

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();
}}};

10-08 13:20