C ++ 11 / templates: выберите правильную перегрузку функции

В отношениях с этот вопрос, это, возможно, слишком упрощенно, я приведу здесь более сложный пример. Проблема, которую я притворяюсь, изображена с помощью следующего кода:

// test3.cpp

using namespace std;

template<typename T>
struct exer
{
template<typename R, typename... rArgs, typename... pArgs>
R operator()(R(T::*f)(rArgs...), pArgs&&... args)
{
return (t.*f)(forward<pArgs>(args)...);
}

T t;
};

struct A
{
int addition() { return 0; }

template<typename... Args>
int addition(int a, Args... args) { return a + addition(args...); }
};

struct B
{
public:
template<typename... Args>
int addition(Args&&... args)
{
return m_e(&A::addition, forward<Args>(args)...);
}

private:
exer<A> m_e;
};

int main()
{
B b;

cout << b.addition(1, 2, 3, 4) << endl;
}

Эта проблема здесь, в инстанции B::addition, тип &A::addition не известно, потому что существуют различные перегрузки. Более того, B::addition не знает также, какая перегрузка должна использоваться. Компилятор не знает, пока не будет вызвана функция. Но, чтобы правильно указать, какая перегрузка должна использоваться в exer<A>::operator()Мне нужно сделать кастинг &A::addition привести его к правильной перегрузке.

Как мне извлечь тип правильной перегрузки целевой функции?

1

Решение

Поменяй вопрос. Если вы можете сделать exer возьмите вызываемый объект вместо указателя на функцию-член, например так:

template<typename T>
struct exer
{
T t;
template<typename F, typename... pArgs>
auto operator()(F f, pArgs&&... args)
-> decltype(f(t, forward<pArgs>(args)...))
{
return f(t, forward<pArgs>(args)...);
}

};

Тогда вы можете сделать это вместо этого:

struct B
{
public:
template<typename... Args>
int addition(Args&&... args)
{
struct Invoker {
auto operator()(A& a, Args&&... args) const
->decltype(a.addition(std::forward<Args>(args)...))
{ return a.addition(std::forward<Args>(args)...); }
};
return m_e(Invoker(), forward<Args>(args)...);
}

private:
exer<A> m_e;
};

Теперь выбираем правильный A::addition выполняется компилятором с использованием нормальных правил разрешения перегрузки.

Вместо Invoker Вы можете использовать лямбда-выражение, которое уменьшает количество повторений:

        return m_e( [](A& a, Args&&... as) {
return a.addition(forward<Args>(as)...);
},
forward<Args>(args)...);
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]