2012-05-31 9 views
10

Synopsis

ich mit der Herstellung C++ 11-Code Clang kompatibel bin zu kämpfen und lief in einen Fall, in dem GCC> = 4.6 akzeptiert Code und Clang> = 3,1 nicht. Clang hält eine candidate constructor not viable.Clang Ausgabe: implizite Typumwandlung bei Bauzeiten

Einzelheiten

Hier ist ein Beispiel, das Problem zu veranschaulichen abgespeckte:

#include <utility> 

template <typename...> 
struct T; 

template<> 
struct T<> 
{ 
    typedef T super; 

    constexpr T() { } 

    template <typename... Args> 
    T(Args&&...) { } 

}; 

template <typename Head, typename... Tail> 
struct T<Head, Tail...> : T<Tail...> 
{ 
    typedef T<Tail...> super; 

    Head head; 

    T(Head arg) : super(), head(std::move(arg)) { } 
}; 


struct void_type 
{ 
    constexpr void_type() { } 
    constexpr void_type(const void_type&) { } 
    void_type& operator=(const void_type&) = default; 

    template <typename Arg0, typename... Args> 
    void_type(Arg0&&, Args&&...) { } 
}; 

struct atom { }; 

int main() 
{ 
    atom a; 
    T<void_type> t(a); 

    return 0; 
} 

Der Fehler, den ich bekommen ist:

ctor-init.cpp:44:18: error: no matching constructor for initialization of 'T<void_type>' 
    T<void_type> t(a); 
       ^~ 
ctor-init.cpp:19:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'atom' to 'const T<void_type>' for 1st argument; 
struct T<Head, Tail...> : T<Tail...> 
    ^
ctor-init.cpp:25:5: note: candidate constructor not viable: no known conversion from 'atom' to 'void_type' for 1st argument; 
    T(Head arg) : super(), head(std::move(arg)) { } 
    ^
1 error generated. 

Ich verstehe nicht, warum über den Mangel Klirren beklagt einer Konvertierungsmöglichkeit, weil ich denke, dass dieser "Catch-All" -Konstruktor funktionieren sollte:

template <typename Arg0, typename... Args> 
void_type(Arg0&&, Args&&...) { } 

So ist der Fehler, den ich bin verwirrt über ist:

ctor-init.cpp:25:5: note: candidate constructor not viable: no known conversion from 'atom' to 'void_type' for 1st argument; 
    T(Head arg) : super(), head(std::move(arg)) { } 
    ^

Immerhin GCC den Code akzeptiert. Ist das vielleicht ein Clang Bug? (Ich verwende den neuesten Clang aus dem LLVM Git Repository.)

+0

@dirkgently: Mit diesem Namen sollten Sie jedoch auch mit diesem abgespeckten Beispiel helfen können. Schließlich bist du der Detektiv, der Schrödingers Cat gefunden hat. – LiKao

+1

Was passiert, wenn Sie versuchen, einen void_type direkt vom Atom zu erzeugen: 'void_type v (a)'? –

+0

@DaveS: das kompiliert einfach gut. Gibt es einen Hinweis darauf, warum die implizite Konvertierung im Konstruktor fehlschlägt? – mavam

Antwort

1

In der Tat war dies ein Clang Bug. Es stellte sich heraus, dass variadische Konstruktoren fälschlicherweise als explizit markiert wurden. Fixed in Clang r158040.

Verwandte Themen