如何保证 std::variant 的复制省略?
How to guarantee copy elision with std::variant?
我有这种类型:
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)...) {}
};
我想围绕 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
实际上并不完全向前——纯右值并不像纯右值那样向前。 (这对我来说很有意义;我认为这样做是不可能的。)我可以通过将 demonstration
更改为以下内容来使 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
以便它可以从纯右值构造 std::variant
(或其他标记的联合)?我可以更改 container
但无法更改 immobile
.
你滥用演员表
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();
}}};
我有这种类型:
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)...) {}
};
我想围绕 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
实际上并不完全向前——纯右值并不像纯右值那样向前。 (这对我来说很有意义;我认为这样做是不可能的。)我可以通过将 demonstration
更改为以下内容来使 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
以便它可以从纯右值构造 std::variant
(或其他标记的联合)?我可以更改 container
但无法更改 immobile
.
你滥用演员表
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();
}}};