我有一些类(class),例如
class A {
public:
void OnStageOne() {}
void OnStageTwo() {}
void OnStageThree() {}
};
class B {
public:
void OnStageOne() {}
void OnStageTwo() {}
void OnStageThree() {}
};
class C {
public:
void OnStageOne() {}
void OnStageTwo() {}
void OnStageThree() {}
};
我有一些 vector 来存储它们:
std::vector<A> va;
std::vector<B> vb;
std::vector<C> vc;
现在我需要一些这样的操作:call OnStageXXX
vector 的所有元素,所以我编写了一个如下的模板函数:
template <typename T, void(T::*F)()>
void ForAll(std::vector<T> vector) {
for (auto& item : vector) {
(item.*F)();
}
}
它工作得很好,除了我必须使用这样的语法:
ForAll<A, &A::OnStageOne>(va);
由于第一个模板参数可以推导出参数va
,有什么办法可以让代码更简洁吗?喜欢ForAll<OnStageOne>(va);
?
或者,如果这是一个 A/B 问题,我可以用任何方式写类似 ForAll<OnStageXXX>(va);
的内容。调用OnStageXXX
vector 的每个元素?
附注我尝试过 std::for_each
,但这会使语法变得更长。我来这里是为了寻找更短的语法来执行此操作(如果有的话)。
最佳答案
在 c++17 :
template <auto F, typename T>
void ForAll(std::vector<T>& vector) {
for (auto& item : vector) {
(item.*F)();
}
}
用法:
ForAll<&A::OnStageOne>(va);
在 c++20 :
constexpr auto OnStageOne = [] (auto& t) -> decltype(t.OnStageOne()) {
return t.OnStageOne();
};
constexpr auto OnStageTwo = [] (auto& t) -> decltype(t.OnStageTwo()) {
return t.OnStageTwo();
};
constexpr auto OnStageThree = [] (auto& t) -> decltype(t.OnStageThree()) {
return t.OnStageThree();
};
template <auto F, typename T>
requires requires (T t) { F(t); }
void ForAll(std::vector<T>& vector) {
for (auto& item : vector) {
F(item);
}
}
用法:
ForAll<OnStageOne>(va);
在 c++11/c++14 (以及之前没有基于范围的 for 循环):
struct OnStageOne {
template <typename T>
void operator()(T& t) const { t.OnStageOne(); }
};
struct OnStageTwo {
template <typename T>
void operator()(T& t) const { t.OnStageTwo(); }
};
struct OnStageThree {
template <typename T>
void operator()(T& t) const { t.OnStageThree(); }
};
template <typename F, typename T>
void ForAll(std::vector<T>& vector) {
for (auto& item : vector) {
F{}(item);
}
}
用法:
ForAll<OnStageOne>(va);
关于c++ - 让模板函数通过函数参数选择类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62170041/