2016-05-06 5 views
1

Ich habe einen folgenden Anwendungsfall, der verursacht Clang, um Fehler zu emittieren.Clang Fehler: Hinweis: Kandidat Konstruktor (der implizite Move Constructor) nicht durchführbar:

#include <iostream> 
#include <type_traits> 

class A 
{ 
    public: 
     int x; 
     A(int g):x(g){} 
}; 

class B : public A 
{ 
    public: 
     int y; 
     B(int p):A(p),y(p) {} 
}; 

class Holder 
{ 
    template<typename T> 
     Holder(typename std::enable_if<!std::is_same<T,A>::value 
        && std::is_base_of< A , T>::value >::type&& val) 
     : b (std::forward<T>(val)) 
     {} 


    private: 
     B b; 
}; 

int main() 
{ 
    B b(10); 

    Holder h(b); 
} 

Der Fehler ist als

forward.cpp:35:12: error: no matching constructor for initialization of 'Holder' 
    Holder h(b); 
     ^~ 
forward.cpp:18:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'B' to 'const Holder' for 1st argument 
class Holder 
    ^
forward.cpp:18:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'B' to 'Holder' for 1st argument 
class Holder 
    ^
forward.cpp:21:9: note: candidate template ignored: couldn't infer template argument 'T' 
     Holder(typename std::enable_if<!std::is_same<T,A>::value 
     ^
1 error generated. 

folgt, wenn sie mit clang++ --std=c++11 forward.cpp zusammengestellt.

Was fehlt mir hier?

Ich habe bereits this und this Fragen konsultiert, aber sie schien nicht meinen Anwendungsfall zu lösen.

+1

Die wichtige Botschaft die letzte ist. Der Compiler kann nicht auf T schließen. – MikeMB

+2

Sie sollten über [nicht-abgeleiteten Kontext] (http://StackOverflow.com/questions/25245453/what-is-aNondeduced-Context?lq=1) lesen, um zu sehen, warum Compiler kann "T" nicht von "B" ableiten. –

Antwort

3

Sie vergessen, den zweiten Parameter von std::enable_if angeben (die standardmäßig void)

template<typename T> 
Holder(typename std::enable_if<!std::is_same<T, A>::value 
       && std::is_base_of< A , T>::value, T>::type&& val) 
    : b (std::forward<T>(val)) 
    {} 

Aber wie auch immer, T in einem nicht ableitbar Zusammenhang wäre. Sie können

tun
template<typename T> 
Holder(T&& val, 
     typename std::enable_if<!std::is_same<typename std::decay<T>::type, A>::value 
           && std::is_base_of<A, typename std::decay<T>::type>::value, 
           std::nullptr_t>::type = nullptr) 
    : b (std::forward<T>(val)) 
    {} 

oder

template<typename T, 
     typename std::enable_if<!std::is_same<typename std::decay<T>::type, A>::value 
           && std::is_base_of<A, typename std::decay<T>::type>::value, 
           std::nullptr_t>::type = nullptr> 
Holder(T&& val) 
    : b (std::forward<T>(val)) 
    {}