【问题标题】:choose among 3 different maps on condition根据条件在 3 个不同的地图中进行选择
【发布时间】:2017-03-21 22:31:10
【问题描述】:

我有 3 个不同的 C++ 映射声明。

map<string, string> map1; 
map<string, int> map2; 
map<string, double> map3; 

我想根据情况使用其中一张地图。比方说

if (map_value == "map1") { default_map = map1; } 
else if (map_value == "map2") { default_map = map2; } 
else { default_map = map3; } 

我的问题是我不知道如何在 C++ 中声明 default_map 可以根据条件进行更改。我期待 C++ 中的 map&lt;Object,Object&gt; default_map 声明。

编辑。 我选择stringintdouble 作为假设对象。实际的map1map2map3 存储函数指针。根据地图中的值,我调用不同的函数。函数签名是相同的,但那些函数指针来自不同的类。本质上,class Avoid funcA(string);class Bvoid funcA(string);class Cvoid funcA(string);funcA 的实现方式因类而异。

感谢任何帮助。

【问题讨论】:

  • 您打算如何使用default_map
  • 换句话说,你会如何处理你假设的Object
  • variant&lt;std::map&lt;std::string, std::string&gt;, std::map&lt;std::string, int&gt;, std::map&lt;std::string, double&gt;&gt; ?
  • @Kerrek SB 我选择string, int, and double 作为假设对象。实际的 map1、map2 和 map3 存储函数指针。根据地图中的值,我调用不同的函数。
  • @Jarod42 我不确定如何使用 Variant。我可以将default_map 声明为变体并将default_map 分配给map1, map2 or map3吗?

标签: c++ dictionary stl stdmap


【解决方案1】:

鉴于您在 cmets 中的说明,我可以提供以下建议:

std::function<R(K, T1, T2, T3)> look_up_and_call;

X x;
Y y;
Z z;

if (map_value == "map1") {
  look_up_and_call =
      [&x, &map1](K key T1 t1, T2 t2, T3 t3) { return (x.*map1[key])(t1, t2, t3); }
} else if (map_value == "map2") {
  look_up_and_call =
      [&y, &map2](K key T1 t1, T2 t2, T3 t3) { return (y.*map2[key])(t1, t2, t3); }
} else {
  look_up_and_call =
      [&z, &map3](K key T1 t1, T2 t2, T3 t3) { return (z.*map3[key])(t1, t2, t3); }
}

现在对于任何给定的映射键 key,您可以这样调用绑定函数:

R result = look_up_and_call(key, arg1, arg2, arg3);

我已经稍微简化了代码,例如我们假设地图元素总是非空的成员函数指针。您可以调整此方案以允许其他类型的指针,并且实际代码可能应该处理不存在的键。您还可以编写类似的函数来向地图添加元素。

【讨论】:

  • 这正是我想要的。您介意在答案和链接文档中解释[&amp;x, &amp;map1](K key T1 t1, T2 t2, T3 t3) 部分吗?我可以在其中阅读更多相关信息?我会接受这个作为答案。
  • @pseudo:这是一个 lambda 表达式。
  • 太棒了。谢谢。
【解决方案2】:

C++ 具有足够强的类型,因此您在此处执行所需的操作会有些困难。

我可以看到几个明显的可能性。一种是使用 Boost Variant 之类的东西来存储值:

std::map<string, boost::variant<string, int, double> > mapN;

这将让您将stringintdouble 中的任何一个与给定字符串关联作为键。变体类型基本上是一个有区别的联合——也就是说,它可以存储任何一种指定的类型,并且有一个字段告诉任何特定实例中存在哪个类型。

另一种可能性是拥有一个看起来像是为所有三种值类型重载的单个函数,这样您就可以在调用站点上拥有外观统一的代码:

void save_map(std::string const &key, std::string const & val) { 
    map1[key] = val;
}

void save_map(std::string const &key, int val) { 
    map2[key] = val;
}

void save_map(std::string const &key, double val) { 
   map3[key] = val;
}

这让save_map("foo", bar); 之类的代码适用于bar 作为三种指定类型中的任何一种(加上隐式转换)。但是请注意,最初看起来最明显的检索值设计是行不通的。特别是,你不能重载返回类型,所以你不能有类似的东西:

std::string get_map(std::string);
int get_map(std::string);
double get_map(std::string);

你不能重载返回类型,所以重载的类型必须作为参数传递:

void get_map(std::string const &key, string &dest);
void get_map(std::string const &key, int &dest);
void get_map(std::string const &key, double &dest);

至于这些(或其他一些可能性)中的哪一个有意义:这将取决于你真正想要完成的事情——你没有告诉我们足够多的事情来给出有意义的答案。

【讨论】:

  • 从C++17开始可以直接使用std::variant(#include )。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-21
  • 1970-01-01
  • 2014-11-26
  • 1970-01-01
  • 2018-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多