提升变体复制语义

Posted

技术标签:

【中文标题】提升变体复制语义【英文标题】:boost variant copy semantics 【发布时间】:2015-01-09 15:32:27 【问题描述】:

我想知道 boost 变体的复制语义是什么。我检查了源代码,这对我来说有点莫名其妙,所以我想知道,在示例代码中,如果我的 getVal(name) 函数在返回时复制了底层向量?如果是这样,我应该将其更改为返回的引用 (&) 吗?

using Val = boost::variant<std::vector<int>, std::vector<std::string>>;

Val getVal(std::string& name) 
 return map[name];// where map is std::map<std::string, Val>

【问题讨论】:

如果你改变它,它可能应该是一个常量引用。 【参考方案1】:

是的,您的 getVal 返回整个向量的副本(包括所有元素字符串的副本,例如)。

是的,返回一个引用可以解决这个问题。


注意您还可以有一个存储引用的变体。在这种情况下,通过“值”返回它仍然具有与返回引用相同的语义:

using Ref = variant<std::vector<int>&, std::vector<std::string>&>;

Ref getVal(std::string& name) 
   return map[name]; // where map is std::map<std::string, Val>

具有从Ref 转换为Val(反之亦然)的必要机制的完整示例:

Live On Coliru

#include <boost/variant.hpp>
#include <map>
#include <vector>
#include <string>


using Val = boost::variant<std::vector<int>, std::vector<std::string>>;
using Ref = boost::variant<std::vector<int>&, std::vector<std::string>& >;

std::map<std::string, Val> map 
     "first", std::vector<int>  1,2,3,4  ,
     "2nd",   std::vector<std::string>  "five", "six", "seven", "eight"  
;

namespace  // detail
    template <typename T>
    struct implicit_convert : boost::static_visitor<T> 
        template <typename U> T operator()(U&& u) const  return std::forward<U>(u); 
    ;


Ref getVal(std::string& name) 
    return boost::apply_visitor(implicit_convert<Ref>(), map[name]);


#include <iostream>

int main() 
    for (auto i : boost::get<std::vector<int>         >(map["first"])) std::cout << i << " ";
    for (auto i : boost::get<std::vector<std::string> >(map["2nd"]))   std::cout << i << " ";

输出:

1 2 3 4 five six seven eight 

没有任何向量被复制

【讨论】:

以上是关于提升变体复制语义的主要内容,如果未能解决你的问题,请参考以下文章

提升精神 x3 变体和 std::pair

当所有变体的库存水平为 0 时,以编程方式复制 WooCommerce 产品

我如何使用一个主题来设置所有材质 UI 输入的样式,就好像它们有一个变体 ='outlined' 一样? [复制]

堆对象自然不支持复制语义

复制语义和比较

c_cpp 复制和移动语义