C++ 处理包含仅移动类型的变体

C++ 处理包含仅移动类型的变体,c++,c++17,std-variant,c++20,c++14,c++11,C++,C++17,Std Variant,C++20,C++14,C++11,考虑以下代码: #包括 #包括 #包括 模板结构重载:Ts。。。{使用Ts::运算符()…;}; 模板重载(Ts…)->重载; 结构foo{ int f; foo(int n):f(n){} }; 结构条{ std::字符串b; }; 使用未格式化的_variant=std::variant; 使用变平的变量=标准::变量; 展平变量展平(常数未展平变量&v){ 回访( 超载{ [](int v)->扁平化变量{ 返回v; }, [](常量std::string&s)->扁平化变量{ 返回s;

考虑以下代码:

#包括
#包括
#包括
模板结构重载:Ts。。。{使用Ts::运算符()…;};
模板重载(Ts…)->重载;
结构foo{
int f;
foo(int n):f(n){}
};
结构条{
std::字符串b;
};
使用未格式化的_variant=std::variant;
使用变平的变量=标准::变量;
展平变量展平(常数未展平变量&v){
回访(
超载{
[](int v)->扁平化变量{
返回v;
},
[](常量std::string&s)->扁平化变量{
返回s;
},
[](const std::unique_ptr&f)->扁平化_变体{
返回*f;
},
[](const std::unique_ptr&b)->扁平化_变体{
返回*b;
},
},
v
);
}
int main()
{
不平坦的_变体uv{std::make_unique(42)};
自动fv=展平(uv);
std::cout
模板结构是:std::false_type{}的_实例_;
模板结构是:std::true_type{}的_实例_;
样板
constexpr bool是_v的_instance _=是_instance _of::value;
展平变量展平(未展平变量常量和v){
返回标准::访问([](自动const&e)->扁平化变量{
使用T=std::decation\u T;
if constexpr(是v的实例){
返回*e;
其他的
返回e;
},v);
}
我们添加了一个要分派的特征,然后使用if constexpr来拥有两个函数体

在中国,我们有更多的选择

[]<class T>(T const& e)->flattened_variant{
  if constexpr (is_instance_of_v<std::unique_ptr, T>){
[](T const&e)->扁平化变量{
if constexpr(是v的实例){
然后,回到重载解决方案,我们有:

[]<class T>(std::unique_ptr<T> const&)
[](std::unique\u ptr const&)

模板
concept-instance-of=is-instance-of::value;
然后

[](自动施工与评价实例)

[]扁平化变量{
使用T=std::decation\u T;
返回constexpr_分支(
例如,
[](自动常量&e){return*e;},
[](自动常量&e){return e;}
)(e) );
},v);
}
回到(您从哪里获得变体?),您可以创建一个外部类:

template<class R>
struct flatten {
  template<class T>
  R operator()(std::unique_ptr<T> const& p)const{
    return *p;
  }
  template<class T>
  R operator()(T const& v)const{
    return v;
  }
};
模板
结构展平{
样板
R运算符()(std::unique_ptr const&p)const{
返回*p;
}
样板
R运算符()(T常量和v)常量{
返回v;
}
};
那就做一个

return std::visit( flatten<flattened_variant>{}, v );
returnstd::visit(展平{},v);
模板结构是:std::false\u type{}的实例;
模板结构是:std::true_type{}的_实例_;
样板
constexpr bool是_v的_instance _=是_instance _of::value;
展平变量展平(未展平变量常量和v){
返回标准::访问([](自动const&e)->扁平化变量{
使用T=std::decation\u T;
if constexpr(是v的实例){
返回*e;
其他的
返回e;
},v);
}
我们添加了一个要分派的特征,然后使用if constexpr来拥有两个函数体

在中国,我们有更多的选择

[]<class T>(T const& e)->flattened_variant{
  if constexpr (is_instance_of_v<std::unique_ptr, T>){
[](T const&e)->扁平化变量{
if constexpr(是v的实例){
然后,回到重载解决方案,我们有:

[]<class T>(std::unique_ptr<T> const&)
[](std::unique\u ptr const&)

模板
concept-instance-of=is-instance-of::value;
然后

[](自动施工与评价实例)

[]扁平化变量{
使用T=std::decation\u T;
返回constexpr_分支(
例如,
[](自动常量&e){return*e;},
[](自动常量&e){return e;}
)(e) );
},v);
}
回到(您从哪里获得变体?),您可以创建一个外部类:

template<class R>
struct flatten {
  template<class T>
  R operator()(std::unique_ptr<T> const& p)const{
    return *p;
  }
  template<class T>
  R operator()(T const& v)const{
    return v;
  }
};
模板
结构展平{
样板
R运算符()(std::unique_ptr const&p)const{
返回*p;
}
样板
R运算符()(T常量和v)常量{
返回v;
}
};
那就做一个

return std::visit( flatten<flattened_variant>{}, v );
returnstd::visit(展平{},v);

那么您想将访问模式匹配到两个lambda中的一个吗?我能为一个is unique ptr trait做一点代码吗?是的……unique ptr trait很好。C++20?
[](const std::unique ptr&u ptr)
是一个简单的解决方案。我现在不使用C++20…但这种lambda叫什么?这一定是lambda有什么原因吗?你没有捕获任何东西,所以让它们成为lambda似乎没有意义。只需创建一个
扁平化\u visitor
类并完成它。所以你想模式匹配分派一个visi两个lambda中的一个?我能为一个is unique ptr trait做一点代码吗?是的…unique_ptr trait很好。C++20?
[](const std::unique_ptr&u ptr)
是一个简单的解决方案。我现在不使用C++20…但这种lambda叫什么?这一定是lambda有什么原因吗?你没有捕获任何东西,所以让它们成为lambda似乎毫无意义。只需创建一个
flatte_visitor
类并完成它。还有
模板co选项ncept instance_of=is_instance_of _v;
允许
[](auto const&e的instance_)
。这应该足够满足大多数人的语法选择。@添加了故事,删除了不太漂亮的,还添加了概念T。还有
模板concept instance_of=is_of _v;
允许
[](auto const&e的实例)
。这应该足够满足大多数人的语法选择。@添加了故事,删除了不太漂亮的故事,还添加了概念T。
return std::visit( flatten<flattened_variant>{}, v );