2016-08-19 169 views
3

我有以下情形:C++模板扣除不能推斷出模板參數

struct AP; 
struct B 
{ 
    B() : m(2) {} 
    int m; 
}; 

struct A : private B 
{ 
    A() : B(), n(1) {} 
private: 
    int n; 
    friend AP; 
}; 

struct AP 
{ 
    AP(A& a) : a_(a) {} 

    template<typename T> 
    struct A_B { 
     using type = typename std::enable_if< std::is_base_of< typename std::remove_reference<T>::type, 
                   A >::value, 
                    T >::type; 
    }; 

    template<typename T> 
    operator typename A_B<T>::type() 
    { 
     return static_cast<T>(a_); 
    } 

    template<typename T> 
    typename A_B<T>::type get() 
    { 
     return static_cast<T>(a_); 
    } 

    int& n() { return a_.n; } 
private: 
    A& a_; 
}; 

int main() 
{ 
    A a; 
    AP ap(a); 
    ap.n() = 7; 
    const B& b = ap.get<const B&>(); 
    //const B& b = ap; candidate template ignored: couldn't infer template argument 'T' 
    //auto b = static_cast<const B&>(ap); candidate template ignored: couldn't infer template argument 'T' 
    std::cout<<b.m; 
} 

註釋行不會進行編譯。 Clang ++注意到「候選模板被忽略:無法推斷模板參數'T'」

爲什麼我無法使用演算操作符獲得對A的基礎的引用? 我認爲代碼看起來會更好。

+1

你的註釋行嘗試轉換'ap'進式B'的''同時參考ap'類型爲'AP',與'B'和'A'無關。你期望如何工作? – wasthishelpful

+0

@wasthishelpful:我認爲OP試圖做的是將'AP'實例的'a_'成員轉換爲'B',這應該是有效的,因爲'A'從'B'派生。 – AndyG

回答

0

我在這裏找到了答案:http://www.mersenneforum.org/showthread.php?t=18076

這是關鍵:「如果你希望編譯器來推斷參數類型,這些類型必須不依賴型」

有了這個它編譯:

template<typename T> 
operator T() 
{ 
    static_assert(std::is_base_of< typename std::remove_reference<T>::type,A >::value, 
         "You may cast AP only to A's base classes."); 
    return static_cast<T>(a_); 
} 
1

你發佈的答案是有效的,但是過度殺傷,除非你真的想要static_assert消息。

經典模板作品就好在這種情況下,因爲A已經轉換爲B

struct AP 
{ 
    AP(A& a) : a_(a) {} 

    template<typename T> 
    operator T() 
    { 
     return a_; 
    } 

    template<typename T> 
    T get() 
    { 
     return a_; 
    } 

    int& n() { return a_.n; } 
private: 
    A& a_; 
}; 

Demo