C++ 在C+中是否有一种优雅的方式来表示包含不同类型的映射+;?

C++ 在C+中是否有一种优雅的方式来表示包含不同类型的映射+;?,c++,types,C++,Types,我正在构建一个类,我想使用各种参数来配置它,这些参数可以是:int、double和string(或者const char*)。在Ruby这样的语言中,我将构建一个初始化函数,该函数接受一个字符串键控的哈希值。例如: class Example def init_with_params params puts params end end e = Example.new e.init_with_params({ "OutputFile" => "/tmp/out.txt",

我正在构建一个类,我想使用各种参数来配置它,这些参数可以是:
int
double
string
(或者
const char*
)。在Ruby这样的语言中,我将构建一个初始化函数,该函数接受一个字符串键控的哈希值。例如:

class Example
  def init_with_params params
    puts params
  end
end

e = Example.new
e.init_with_params({ "OutputFile" => "/tmp/out.txt", "CaptureFPS" => 25.0, "RetryDelaySeconds" => 5 })
<>如何在C++中创建类似的行为?< /P> 环顾四周,我发现有几篇帖子在谈论
boost::variant
。我宁愿避免使用boost,如果通过将不同的类型限制为我上面提到的3种类型,就可以得到一个相当干净的解决方案

编辑
我同意使用设计良好且经过广泛测试的代码(如Boost.Variant)比重新实现相同的想法要好得多。在本例中,问题简化为仅使用3种基本类型,因此我正在寻找实现它的最简单方法

如果您想避免使用Boost,可以将Boost.Variant的代码复制粘贴到您的项目中。无论如何,这只是标题。或者你可以通过实现一个通常被称为“有区别的联合”来重新发明轮子。

如果我理解得很好,你需要一个
std::map
(或者更好的是,一个
std::unordered_map
,因为你需要哈希),其中
a
是一个字符串,
B
可以是
int
double
std::string


对于
B
可以使用
boost::any
。否则,如果你不想使用Boost,你可以使用一个歧视的<代码>联合<代码>。< /P> < P>最有意义的事情是使用Boo.Stand,它是由C++程序员开发的,并被数百个项目磨练和测试。 但如果这不是你的选择,我看到以下备选方案:

  • 重新实现增强。你自己改变。这将是一个很好的学习练习,但它需要很多时间才能正确(然后需要更多的时间来修复所有的bug)

  • 按照时间效率辞职,将所有类型存储在
    std::string
    中,并在getter中转换它们(最初在@Galik的评论中建议)

  • 以内存效率为基础,将这三种类型都存储在您的类中

  • 如果您特别反对Boost,请使用另一个提供变体类型的库(如)


  • 下面是我经常用来存储程序配置属性的精简版本,也许您会发现它很有用:

    #include <map>
    #include <string>
    #include <sstream>
    #include <fstream>
    #include <iostream>
    #include <initializer_list>
    
    class config
    {
        // everything is stored internally as std::strings
        // usually read from a configuration file
        typedef std::map<std::string, std::string> prop_map;
        typedef prop_map::const_iterator prop_map_citer;
    
        prop_map props;
    
    public:
        // example constructor. Normally I have a method to read the
        // values in from a file
        config(std::initializer_list<std::pair<std::string, std::string>> list)
        {
            for(const auto& p: list)
                props[p.first] = p.second;
        }
    
        // values are converted as they are requested to whatever types
        // they need to be. Also a default may be given in case the value
        // was missing from the configuration file
        template<typename T>
        T get(const std::string& s, const T& dflt = T()) const
        {
            prop_map_citer found = props.find(s);
    
            if(found == props.end())
                return dflt;
    
            T t;
            std::istringstream(found->second) >> std::boolalpha >> t;
            return t;
        }
    
        // std::strings need special handling (no conversion)
        std::string get(const std::string& s, const std::string& dflt = "") const
        {
            prop_map_citer found = props.find(s);
            return found != props.end() ? found->second : dflt;
        }
    
    };
    
    int main()
    {
        const config cfg =
        {
            {"OutputFile", "/tmp/out.txt"}
            , {"CaptureFPS", "25.0"}
            , {"RetryDelaySeconds", "5"}
        };
    
        std::string s;
        float f;
        int i;
    
        s = cfg.get("OutputFile");
        f = cfg.get<float>("CaptureFPS");
        i = cfg.get<int>("RetryDelaySeconds");
    
        std::cout << "s: " << s << '\n';
        std::cout << "f: " << f << '\n';
        std::cout << "i: " << i << '\n';
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    类配置
    {
    //所有内容都以std::strings的形式存储在内部
    //通常从配置文件读取
    typedef std::map prop_map;
    typedef属性映射::常量迭代器属性映射;
    道具地图道具;
    公众:
    //示例构造函数。通常我有一个方法来读取
    //文件中的值
    配置(标准::初始值设定项\u列表)
    {
    用于(常数自动和p:列表)
    道具[p.first]=p.second;
    }
    //值在被请求时转换为任何类型
    //它们必须是。如果值为
    //配置文件中缺少
    模板
    T get(const std::string&s,const T&dflt=T())const
    {
    prop\u map\u citer found=props.find(s);
    if(found==props.end())
    返回dflt;
    T;
    std::istringstream(发现->秒)>>std::boolalpha>>t;
    返回t;
    }
    //std::字符串需要特殊处理(无转换)
    std::string get(const std::string&s,const std::string&dflt=”“)const
    {
    prop\u map\u citer found=props.find(s);
    return found!=props.end()?found->second:dflt;
    }
    };
    int main()
    {
    常量配置=
    {
    {“OutputFile”,“/tmp/out.txt”}
    ,{“CaptureFPS”,“25.0”}
    ,{“RetryDelaySeconds”,“5”}
    };
    std::字符串s;
    浮动f;
    int i;
    s=cfg.get(“输出文件”);
    f=cfg.get(“CaptureFPS”);
    i=cfg.get(“RetryDelaySeconds”);
    
    std::cout你想做什么?你能让一个类有一个
    int
    double
    string
    ,然后做一个普通的构造函数吗?你可以把所有的值存储为string,然后有
    get()
    方法返回转换为相关类型的字符串。我希望允许灵活的配置,例如从.yaml文件中读取。值的类型不同{int,double,string},因此常规映射不起作用。对于固定数量的普通类型(如
    int
    double
    ,但不是
    std::string
    ),您可以组合一个简单的有区别的并集,使用值的并集和枚举来给出类型。如果它更复杂(一组无界类型或非平凡类型),然后只使用Boost.Variant。它只是标题,而且很容易重新创建。您可以使用
    char*
    将字符串指针导入联合体。当然,在这种情况下,您需要自己进行内存管理。+1,主要用于重新创建轮子。因为这正是避免Boost的意思。+1如果您选择重新创建e轮通过有区别的联合。它看起来像boost::property_树