如何在算法中使用不同命名的成员函数处理 类?
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
而改变类Zoo
和Library
是没有意义的。
为了 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);
}
我用 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
而改变类Zoo
和Library
是没有意义的。
为了 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);
}