2016-08-19 137 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