C ++模板类型,可以存储在std :: map中,然后公开公开地图

时间:2010-09-24 09:11:41

标签: c++ map

我有一个类myclass,它有一个私有成员param_map

class some_class {

 private:
  std::map<std::string,std::shared_ptr<parameter> > param_map;
};

我想公开这个地图以允许其他类,我已经创建了add,delete,get参数方法,这些都是你想的。但是我想公开这个,以便其他类可以遍历地图。

Q1:最安全的方法是什么。

参数也有一个成员值,我想成为int / float / bool,所以一个选项是使用模板定义它

template<class T>
class parameter {
  public:
   T get_value { return value_; }

  private:
   T value_;
}

Q2:但是我如何将这种类型存储在地图中?它将如何改变param_map的定义。另外我会考虑非模板解决方案(但我更喜欢只有一张地图)

PS:我宁愿避免使用boost,我更喜欢使用c ++ x0 std lib,但如果boost是最佳选择,那么我会考虑这一点。如果你也可以发布代码示例,那将是件好事。

此致

标记

3 个答案:

答案 0 :(得分:1)

Q1:您可以公开迭代地图的迭代器,就像std :: map一样。

Q2:您可以使用3个不同的地图,或使用boost :: any来存储该值。如果你想避免提升,你可以存储void *代替boost :: any(但我通常不会采用void *方式 - 我宁愿使用所需的boost部分)。

答案 1 :(得分:1)

Q1:你可以提供一个foreach()成员函数,它接受一个仿函数作为参数。 foreach函数将遍历地图并在地图中的每个项目上调用仿函数。然后调用者可以使用C ++ 0x lambda函数来创建仿函数。

#include <string>
#include <iostream>
#include <map>
#include <algorithm>

using namespace std;

class container {
public:
    container() {
        _m["one"] = 1;
        _m["two"] = 2;
        _m["three"] = 3;
    }

    template <class FN>
    void foreach(FN func) {
        std::for_each(_m.begin(), _m.end(), func);
    }

private:
    map<string, int> _m;
};

void main(int, char** a)
{
    container c;
    c.foreach([](pair<string,int> p) -> void {
        cout << p.first << ", " << p.second << endl;
    });
}

我没有方便的C ++ 0x兼容编译器,因此可能需要进行一些调整才能编译。

Q2:我知道你不想使用提升,但我认为boost.variant可能是你最好的选择。你可以使用一个有区别的联盟,但我会非常犹豫地放弃类型安全性boost.variant给你。

enum type { int_t, float_t, bool_t };

struct item {
    type t;
    union {
        int i;
        float f;
        bool b;
    };
};

答案 2 :(得分:0)

我会使用boost::any作为模板类型。你可以自己重新实现(作为一项很好的练习),但这会浪费你的时间。

至于Q1,为什么不简单地将地图公之于众?你最终会为map中的大多数方法提供加入函数,比如operator [],iterators等。所以公开它并不是一个坏主意:

struct MyClass 
{
    map<string, any> parameters;

    // For convenience
    template <typename T>
    T const& getParameter(string const& s) const
    {
        map<string, any>::const_iterator i = parameters.find(s);
        if (i == parameters.end()) throw /* something */;
        return any_cast<T const&>(*i);
    }

    template <typename T>
    T& getParameter(string const& s)
    {
        map<string, any>::iterator i = parameters.find(s);
        if (i == parameters.end()) throw /* something */;
        return any_cast<T&>(*i);
    }
};

MyClass x; 
x.parameters["foo"] = 2.5;
x.parameters["bar"] = string("Hey");
double xfoo = x.getParameter<double>("foo");
string const& xbar = x.getParameter<string>("bar");
for_each(x.parameters.begin(), x.parameters.end(), baz);