如何在算法中使用不同命名的成员函数处理 类?

How to handle classes with differently named member functions in algorithms?

我用 C++ 实现了一个算法。该算法可以处理具有某些共同属性的不同事物(对象)。该算法需要调用这些对象的一些成员函数。所以,当然,它需要函数名来做到这一点。现在,问题是,算法可能处理的事情可能完全不同。例如,考虑以下说明性代码片段:

struct Zoo {
   using NumAnimals = unsigned short;

   Animal GetAnimal();
   NumAnimals GetNumAnimals();

};

struct Library {
   using NumBooks = size_t;

   Book GetBook();
   NumBooks GetNumBooks();
};

template<typename T>
void f(T t) {
    do_something(t.Get???(), t.GetNum???()); // Get what?
}

用什么代替问号?

我认为将 GetAnimal() 和 GetBook() 替换为 GetThing()、GetItem()、GetObj() 或类似的东西然后让 f 调用该函数会非常不方便。与 GetNumAnimals() 和 GetNumbooks() 类似。但是如何在两个 classes 的实例上调用算法 f 呢?我们可以在这里建立某种 "name translation"(别名)而不会使 Zoo 和 Library 混乱吗?

我想到的一个可能的解决方案是分别从 Zoo 和 Library 派生 class,"proxies" f 中的调用, 例如,对于动物园:

struct ZooProxy : public Zoo {
    using Item = Animal;
    using NumItems = NumAnimals;

    Item GetItem() { return GetAnimal(); }
    NumItems GetNumItems() { return GetNumAnimals(); }
};

然后替换???在 f 中分别按 Item 和 Items。

还有其他(更好的)选择吗?

为了f而改变类ZooLibrary是没有意义的。

为了 f 的目的创建重载函数会更好。您可以在这些函数中添加特定于 f 的代码,而不会影响 类 本身。

template<typename T>
void f(T t) {
    do_something(geItemForF(t), getNumForF(t));
}

Animal const& geItemForF(Zoo const& zoo) { ... }
int getNumForF(Zoo const& zoo) { ... }

Book const& geItemForF(Libraryconst& library) { ... }
int getNumForF(Libraryconst& library) { ... }

还有一种方法。

template<typename T, typename GetItem, typename GetItemCount>
struct Algorithm {
  Algorithm(GetItem&& t, GetItemCount&& f):
    getItem_m(t),
    getItemCount_m(f) {}

  bool operator() (T& t) {
    std::cout << "Executing getItem_m: " << getItem_m(t) << std::endl;
    std::cout << "Executing getItemCount_m: " << getItemCount_m(t) << std::endl;

  }


  GetItem getItem_m;
  GetItemCount getItemCount_m;

};


int main () {

  auto getAnimal = std::bind(&Zoo::GetAnimal, std::placeholders::_1);
  auto getAnimalCount = std::bind(&Zoo::GetNumAnimals, std::placeholders::_1);
  using AnimalAlgorithm = Algorithm<Zoo, decltype(getAnimal), decltype(getAnimalCount)>;

  auto getBook = std::bind(&Library::GetBook, std::placeholders::_1);
  auto GetBookCount = std::bind(&Library::GetNumbooks, std::placeholders::_1);
  using LibraryAlgorithm = Algorithm<Library, decltype(getBook), decltype(GetBookCount)>;


  AnimalAlgorithm aa(std::move(getAnimal), std::move(getAnimalCount));
  LibraryAlgorithm la(std::move(getBook), std::move(GetBookCount));

  Zoo z();
  Zoo z1();
  Library l();

  aa(z);
  aa(z1);
  la(l);

}