从unordered_multimap中从另一个类调用函数?

时间:2019-04-05 02:58:11

标签: c++ templates c++17 function-pointers unordered-map

这与我的最新帖子有关,您可以在这里找到:Creating an unordered_map of std::functions with any arguments。我现在继续将其扩展到课堂上。假设我有三个不同的班级。除了getVariable()setVariable(int)以外,这些类都具有不同的方法。因此,在此示例中,我们将它们分类为ClassAClassBClassC

我也有一个要用作驱动程序的基类。本质上,如果我想在ClassAClassC之间设置变量,我将调用基类的setVariable函数。

#ifndef BASE_CLASS_HPP
#define BASE_CLASS_HPP

#include <unordered_map>
#include <functional>
#include <utility>
#include <string>
#include <any>

template<class A, class B>
class BaseClass
{
  public:
    BaseClass() { bindThem(); }

    std::pair<int,int> getValue()
    {
      // return classA and ClassB's values
    }

    void setValue(int newVal)
    {
      auto iter = functions.equal_range("setValue");
      std::any_cast<void(*)(int)>(mapIter->second)(newVal);
    }
  private:
    std::unordered_multimap<std::string,std::any> functions;

    void bindThem()
    {
      functions.emplace("setValue",&A::setValue);
      functions.emplace("setValue",&B::setValue);
      functions.emplace("getValue",&A::getValue);
      functions.emplace("getValue",&B::getValue);
    }

};

然后我要进入主场

#include <iostream>

#include "baseClass.hpp"
#include "classA.hpp"
#include "classB.hpp"
#include "classC.hpp"

int main()
{
  ClassA a;
  ClassB b;
  ClassC c;

  c.setValue(20);

  BaseClass<ClassA,ClassB> base1;
  BaseClass<ClassA,ClassC> base2;

  base1.setValue(15);

  auto values = base1.getValues();


}

我可以将函数与地图一起放置,但是,当我尝试any_cast时却没有得到任何回报。我也尝试过:

std::any_cast<void(A::*)(int)>(mapIter->second)(newVal);

但是,这也给我带来了必须使用。*或-> *的编译器错误,我已经尝试了所有方法来使其进行编译,但我真的不知道自己在做什么错。我还意识到,如果以这种方式调用它,那么由于我正在使用setVariable命名空间,因此我将无法访问B的A's函数。

无论如何,我可以按照我的意愿使它工作吗?我本质上是在尝试修改这些类的值,而不必制作这些类的任何副本,而是直接从此驱动程序中修改它们。

1 个答案:

答案 0 :(得分:0)

我仍然不太了解这种结构的目的,但是这里有一个选项使它至少可以编译:

#include <unordered_map>
#include <functional>
#include <utility>
#include <string>
#include <any>

template<class A, class B>
class BaseClass
{
  public:
    BaseClass() { bindThem(); }

    std::pair<int,int> getValue()
    {
      auto range = functions.equal_range("getValue");
      return 
        {
          (a.*std::any_cast<int(A::*)()>(*range.first))(),
          (b.*std::any_cast<int(B::*)()>(*range.second))()
        };
    }

    void setValue(int newVal)
    {
      auto range = functions.equal_range("setValue");
      (a.*std::any_cast<void(A::*)(int)>(*range.first))(newVal);
      (b.*std::any_cast<void(B::*)(int)>(*range.second))(newVal);
    }
  private:
    std::unordered_multimap<std::string,std::any> functions;

    void bindThem()
    {
      functions.emplace("setValue",&A::setValue);
      functions.emplace("setValue",&B::setValue);
      functions.emplace("getValue",&A::getValue);
      functions.emplace("getValue",&B::getValue);
    }

    A a;
    B b;
};

class ClassA
{
public:
    void setValue(int){}
    int getValue() {return 0;}
};

class ClassB
{
public:
    void setValue(int){}
    int getValue() {return 1;}
};

int main()
{
    BaseClass<ClassA, ClassB> x;
    x.setValue(3);
    auto i = x.getValue();
}

请注意几件事:

  1. 我已将成员添加到BaseClass,因为要调用成员函数,需要调用一个对象。
  2. 我正在使用equal_range范围内的第一个和最后一个迭代器,但是该范围内的元素顺序是实现定义的。因此,要使事情正常进行,您需要注意区分哪个容器元素对应于类A以及哪个容器元素对应于类B