2013-03-19 52 views
1

關於this question,這可能太簡單了,我在這裏給出一個更復雜的例子。我假裝問題描述用下面的代碼: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的instantation的&A::addition類型是不知道,因爲不同的重載存在。此外,B::addition也不知道必須使用哪種過載。在調用函數之前,它不知道編譯器。但是,爲了正確指定極限過載必須在exer<A>::operator()中使用,我需要鑄造&A::addition以將其轉換爲正確的過載。

如何提取目標函數的正確超載類型?

回答

3

更改問題。如果你可以讓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你可以使用lambda表達式,從而減少一些重複的:

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