HTN*_*TNW 6 c++ variant copy-elision c++17
我有这种类型:
\n\nstruct immobile {\n // other stuff omitted\n immobile(immobile&) = delete;\n immobile(immobile&&) = delete;\n};\nimmobile mk_immobile();\n// e.g. this compiles\n// mk_immobile() is a prvalue and i is its result object\nimmobile i(mk_immobile());\nRun Code Online (Sandbox Code Playgroud)\n\n我也有这个类模板:
\n\ntemplate<typename T>\nstruct container {\n std::variant<T, other_stuff> var;\n template<typename... Args>\n container(Args&&... args)\n : var(std::in_place_index<0>, std::forward<Args>(args)...) {}\n};\nRun Code Online (Sandbox Code Playgroud)\n\n我想container围绕 生成的对象构造mk_immobile(),该immobile对象用于初始化 的变体之一var。
container<immobile> c(mk_immobile());\nRun Code Online (Sandbox Code Playgroud)\n\n然而,这是行不通的。其一,std::variant的构造函数要求std::is_constructible_v<immobile, immobile>,但它不成立。更糟糕的是,即使这个简化版本也失败了:
template<typename T>\nstruct demonstration {\n T t;\n template<typename... Args>\n demonstration(Args&&... args) : t(std::forward<Args>(args)...) {}\n};\ndemonstration<immobile> d(mk_immobile());\nRun Code Online (Sandbox Code Playgroud)\n\n这似乎意味着std::forward实际上并没有完全转发\xe2\x80\x94prvalues 不会作为纯右值转发。(这对我来说很有意义;我认为这样做是不可能的。)我可以demonstration通过将其更改为这样来完成工作:
template<typename T>\nstruct demonstration {\n T t;\n template<typename F>\n demonstration(F&& f) : t(std::forward<F>(f)()) {}\n};\ndemonstration<immobile> d([] { return mk_immobile(); });\nRun Code Online (Sandbox Code Playgroud)\n\n但我看不出有什么办法可以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>;
Run Code Online (Sandbox Code Playgroud)
并用作
container<immobile> c{initializer{[]{
return mk_immobile();
}}};
Run Code Online (Sandbox Code Playgroud)