【问题标题】:Boost variant visitor with variadic template arguments使用可变模板参数提升可变访问者
【发布时间】:2016-06-03 18:37:20
【问题描述】:

在我的一个项目中,我正在积极使用boost::variant,但我偶然发现了一个我自己无法解决的问题。我有一个boost::variant,它可能包含原子数据类型和这些原子数据类型的 STL 容器。

现在,我想计算先前定义的 boost::variant 类型的实例的大小。基本上只有两种可能的功能。原子数据类型的类型只是 1,而 STL 容器的大小定义为其中包含的元素数。

只有 2 个原子数据类型,我实现了以下代码:

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

typedef boost::variant<int, double, std::vector<int>, std::vector<double> > TVariant;

struct sizeVisitor : boost::static_visitor<size_t> {
   size_t operator()(int&) {
    return 1;
    }
   size_t operator()(double&) {
    return 1;
    }

   size_t operator()(std::vector<int>& c) {
    return c.size();
    }

   size_t operator()(std::vector<double>& c) {
    return c.size();
    }
} ;


int main(int argc, char **args) {
    sizeVisitor visitor;
    TVariant var=5;
    std::cout << boost::apply_visitor(visitor, var) << std::endl;
    std::vector<int> vector;
    vector.push_back(6);
    vector.push_back(2);
    var=vector;
    std::cout << boost::apply_visitor(visitor, var) << std::endl;
}

随着原子数据类型数量的增加,我有很多代码重复。我必须为每个新的原子数据类型声明另外两个函数,这可能令人望而却步。

如果下面的代码可以编译就好了:

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

typedef boost::variant<int, double, std::vector<int>, std::vector<double> > TVariant;

struct sizeVisitor : boost::static_visitor<size_t> {
   size_t operator()(boost::variant<int,double>&) {
    return 1;
    }

   size_t operator()(boost::variant<std::vector<int>,std::vector<double>>& c) {
    return c.size();
    }

} ;


int main(int argc, char **args) {
    sizeVisitor visitor;
    TVariant var=5;
    std::cout << boost::apply_visitor(visitor, var) << std::endl;
    std::vector<int> vector;
    vector.push_back(6);
    vector.push_back(2);
    var=vector;
    std::cout << boost::apply_visitor(visitor, var) << std::endl;
}

不幸的是,非编译访问者的第二个最接近的实现可能是什么?

【问题讨论】:

    标签: c++ templates stl boost-mpl boost-variant


    【解决方案1】:

    只需对operator()使用两个函数模板:

    struct sizeVisitor 
        : boost::static_visitor<size_t>
    {
        template <class T>
        size_t operator()(T const&) {
            return 1;
        }
    
        template <class T>
        size_t operator()(std::vector<T> const& v) {
            return v.size();
        }    
    };
    

    模板部分排序规则将确保调用正确的规则。

    【讨论】:

    • 哇。这是一个非常明显的解决方案。非常感谢。我想知道是否还有针对更普遍问题的解决方案,我必须将给定boost::variant 的类型集划分为两个子集,例如分为数字和非数字。我想写一个访问者,为这个属性产生一个布尔值。
    • @FrankSimon 使用 SFINAE - 根据某些类型特征启用一个重载和一个禁用。
    • 我不知道这个概念。看来我必须多学习一点C++。非常感谢这些深刻的见解。我去看看。
    • @FrankSimon 享受你即将掉入的兔子洞吧:)
    • @frank 而不是 sfinae,标记从主 () 分派到辅助方法。更少的混乱,更容易,更容易阅读错误。 { return helper(std::is_numeric&lt;T&gt;{}, t); },其中helper(true_type, T) 获取数字,helper(false_type, T) 获取其余部分。
    猜你喜欢
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    • 2022-01-01
    • 2011-09-28
    • 2013-09-14
    • 2023-03-07
    相关资源
    最近更新 更多