关联std :: tuple容器

时间:2015-03-10 08:53:33

标签: c++ c++11 containers variadic-templates

是否可以定义(以简单的方式,可能重新使用std容器)"关联std::tuple",或换言之," variadiac {{ 1}}"

像这样的东西(这个界面只是为了解释,欢迎其他可能的接口):

std::map

其他理想的约束:

  1. 只有在运行时才知道值/键的集合。但是在编译时,用户知道(值的类型)和键之间的关系。例如,用户在编译时知道AssociativeTuple<std::string> at; // std:string is the key type at.insert<float>("my_float", 3.14); // 1. at.insert<int>("my_int", 42); at.insert<bool>("my_bool", true); at.insert<int>("xyz", 0); at.insert<std::string>("my_string", "hello world!"); assert(get(at, "my_float") == 3.14); // 2. assert(get(at, "my_int") == 42); assert(at["my_string"] == "hello world!"); // 3. assert(std::is_same<at.type_of("my_float")::type, float>) // 4. for (auto it : at) { std::cout << it.first << " = " << it.second; } // 5. 将是"my_float"。换句话说,设置可能的键是固定的,并且对应于键的值的类型在编译时是已知的。在编译时不知道的是&#34;如果&#34;一个键将插入容器内。当然,在编译时不知道映射值的值。
  2. 访问性能,float应该快速
  3. 用户不必记住与密钥相关联的类型
  4. 我真正的问题是get / float / int类型的价值(而我正在做的是存储在bool中的所有内容并转换为{必要时std::map<std::string, float>),但需要一般解决方案。在我的实际情况中,密钥始终是int

3 个答案:

答案 0 :(得分:3)

您可能意味着具有多态值的地图。对于多态值,您可以使用boost::any或更好的boost::variant<>。 E.g:

typedef boost::variant<int, double, std::string> MyVariant;
typedef std::map<std::string, MyVariant> MyPolymorphicMap;

答案 1 :(得分:1)

这个怎么样? (注意:值不是元组;每个键有一个值。)

template<class K> using AnyMap = std::map<K, boost::any>;

AnyMap map;
map["test1"] = 124;
map["test2"] = std::string{ "some text" };

auto value = boost::any_cast<int>(map["test1"]);

答案 2 :(得分:0)

是的,这可以使用一个变体(那里有很多实现)或一般的某种包装器,基于一个联合(在你的情况下是首选方式)或派生自一个公共基类。

对于像get(at, "my_int") == 42这样的东西,你必须重载等于运算符bool operator==(Variant&, int),但这也不应该是一个问题。

你不能做像std::is_same<at.type_of("my_float")::type, float>之类的东西,因为is_same是一个编译时表达式,但是类型(你正在寻找)只在运行时才知道。但是,您仍然可以定义执行该检查的运行时函数。

但是:如果 - 在您的特定情况下 - 您只需要intfloat并且您没有很难记住内存(使用字符串作为键似乎表明这一点),那么我只是使用double因为它可以代表您可能想要存储的任何数字。

另一种可能性是使用两个独立的数据结构(一个用于int,一个用于float)。如果有必要,您还可以围绕这些构建一个rwarpper,以使它们看起来像一个。如果您的programlogic总是在执行查找之前始终知道与键相关联的类型,那么使用多个数据结构可能特别有意义。