В отношениях с этот вопрос, это, возможно, слишком упрощенно, я приведу здесь более сложный пример. Проблема, которую я притворяюсь, изображена с помощью следующего кода:
// 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
привести его к правильной перегрузке.
Как мне извлечь тип правильной перегрузки целевой функции?
Поменяй вопрос. Если вы можете сделать 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)...);
Других решений пока нет …