假设我有两个用于迭代容器的模板函数:
template <typename I, typename C>
It Prev(I i, const C& c) noexcept {
Expects(i != c.end());
if (i == c.begin()) return c.end();
return i - 1;
}
和
template <typename I, typename C>
It Next(I i, const C& c) noexcept {
Expects(i != c.end());
return i + 1;
}
具有使用这些模板的GetNextElement和GetPrevElement的类:
struct MyClass {
std::vector<int> elements;
int* GetNextElement(std::vector<int>::iterator i) {
auto next = Next(i, elements);
if (next == elements.end()) return nullptr;
return &*it;
}
int* GetPrevElement(std::vector<int>::iterator i) {
auto prev = Prev(i, elements);
if (prev == elements.end()) return nullptr;
return &*it;
}
};
除了调用不同的模板外,这两种方法的功能相同。如何将这些转换为可能被称为
的单个成员函数MyClass mc;
// ...
auto it = mc.elements.begin();
auto next = mc.GetElement<Next>(it);
// Or maybe mc.GetElement(it, Next);
答案 0 :(得分:2)
#define OINVOKE(...) __VA_ARGS__(decltype(args)(args)...)
#define OVERLOADS_OF(...) [](auto&&...args)\
noexcept(noexcept(OINVOKE(__VA_ARGS__)))\
->decltype(OINVOKE(__VA_ARGS__))\
{ return OINVOKE(__VA_ARGS__); }
auto fNext=OVERLOADS_OF(Next);
auto fPrev=OVERLOADS_OF(Prev);
然后:
template<auto* pf>
int* GetElement(std::vector<int>::iterator i) {
auto next = (*pf)(i, elements);
if (next == elements.end()) return nullptr;
return &*it;
}
auto it = mc.elements.begin();
auto next = GetElement<&fNext>(it);
需要C ++ 17。
答案 1 :(得分:1)
如果您可以将函数包装在struct
中,则会大大简化此问题。
struct Prev
{
template <typename I, typename C>
I operator()(I i, const C& c) noexcept {
Expects(i != c.end());
if (i == c.begin()) return c.end();
return i - 1;
}
};
struct Next
{
template <typename I, typename C>
I operator()(I i, const C& c) noexcept {
Expects(i != c.end());
return i + 1;
}
};
然后,您可以将它们作为模板参数传递。
struct MyClass
{
public:
auto begin() { return elements.begin(); }
auto end() { return elements.end(); }
template<typename T, typename I>
I GetElement(I iter)
{
return T()(iter, this->elements);
}
private:
std::vector<int> elements;
};
int main()
{
MyClass mc;
auto it = mc.begin();
auto next = mc.GetElement<Next>(it);
auto prev = mc.GetElement<Prev>(it);
}
答案 2 :(得分:0)
您可以尝试以下代码:
template <std::vector<int>::iterator (*FOO)(std::vector<int>::iterator, const std::vector<int>&)>
std::vector<int>::iterator GetElement(std::vector<int>::iterator i)
{
return FOO(i, elements);
}