2012-05-31 12 views
10

Sinossi

sto lottando con fare compatibile C++ 11 Codice Clang e sono imbattuto in un caso in cui GCC> = 4.6 accetta il codice e Clang> = 3.1 non lo fa. Clang ritiene un candidate constructor not viable.Clang problema: Tipo di conversione implicita in fase di costruzione

dettagli

Ecco un tagliati giù esempio per illustrare il problema:

#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; 
} 

L'errore che ottengo è:

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. 

Non capisco il motivo per cui clang lamenta la mancanza di una possibilità di conversione, perché penso che questo costruttore "catch-all" dovrebbe funzionare:

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

Quindi l'errore mi sono confuso circa è:

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)) { } 
    ^

Dopo tutto, GCC accetta il codice. È forse un bug di Clang? (Sto usando l'ultimo Clang dal repository git LLVM.)

+0

@dirkgently: con questo nome, tuttavia, si dovrebbe essere in grado di aiutare anche con questo esempio ridotto. Dopotutto sei il detective che ha trovato Schrödingers Cat. – LiKao

+1

Cosa succede se provi a creare direttamente un void_type dall'atomo: 'void_type v (a)'? –

+0

@Dave: questo compila bene. Ti dà un'idea del perché la conversione implicita nel costruttore fallisce? – mavam

risposta

1

In effetti, questo era un bug Clang. Si è scoperto che i costruttori variadici sono erroneamente contrassegnati come espliciti. Fixed in Clang r158040.

Problemi correlati