2013-06-02 13 views
5

Mentre la codifica in giro in un progetto su cui sto lavorando, ho scoperto qualcosa di veramente strano:perché non si può risolvere questo gcc utilizzando dichiarazione al tipo corretto

namespace detail { 

    struct tuplelike_tag { }; 
    struct arraylike_tag { }; 

    template<typename> 
    struct call_with_traits; 

    template<typename... Ts> 
    struct call_with_traits<std::tuple<Ts...>> { 
     using tag = tuplelike_tag; 

     enum { size = sizeof...(Ts) }; 
    }; 

    template<typename T, std::size_t Sz> 
    struct call_with_traits<std::array<T, Sz>> { 
     using tag = arraylike_tag; 

     enum { size = Sz }; 
    }; 

    template<typename T, std::size_t Sz> 
    struct call_with_traits<T[Sz]> { 
     using tag = arraylike_tag; 

     enum { size = Sz }; 
    }; 

    template<typename F, typename T, int... Is> 
    auto call_with(F && f, T && tup, indices<Is...>, tuplelike_tag) -> ResultOf<Unqualified<F>> { 
     return (std::forward<F>(f))(std::get<Is>(std::forward<T>(tup))...); 
    } 

    template<typename F, typename A, int... Is> 
    auto call_with(F && f, A && arr, indices<Is...>, arraylike_tag) -> ResultOf<Unqualified<F>> { 
     return (std::forward<F>(f))(std::forward<A>(arr)[Is]...); 
    } 
} 

template<typename F, typename Cont> 
inline auto call_with(F && f, Cont && cont) -> ResultOf<Unqualified<F>> { 
    using unqualified = Unqualified<Cont>; 
    using traits = typename detail::call_with_traits<unqualified>; 
    using tag  = typename detail::call_with_traits<unqualified>::tag; 
    using no_tag = typename traits::tag; // this is what it's all about 
    return detail::call_with(std::forward<F>(f), std::forward<Cont>(cont), build_indices<traits::size>(), tag()); 
} 

La cosa strana di questo codice è che il tag viene risolto in dettaglio nome :: call_with_traits :: tag;, ma no_tag errori fuori:

error: no type named ‘tag’ in ‘using traits = struct detail::call_with_traits<typename std::remove_cv<typename std::remove_reference<_To>::type>::type>’ 

anche se dovrebbe fare riferimento alla stessa dichiarazione utilizzando nella stessa struct. C'è qualcosa che mi manca, o questo è un bug in GCC?

A live example can be found here, incluso il relativo messaggio di errore da GCC.

+1

Direi che è un bug. Compilano bene su GCC 4.8.0 e su Clang 3.2 –

risposta

6

Questo sembra essere un bug in g ++ 4.7.2. Ecco un esempio minimo:

template<typename> struct A { using tag = int; }; 

template<typename T> 
inline void f() { 
    using AT = A<T>; 
    typename A<T>::tag x; // no error 
    typename AT::tag y; // error 
} 

int main(int argc, char ** argv) { 
    f<int>(); 

    return 0; 
} 

Non ci sono errori se un typedef è usato al posto di una dichiarazione using, o se si utilizza A<int> invece di A<T>.

+0

Andy Prowl ha già suggerito che fosse il caso, ma grazie per averlo verificato. Per ora userò il FQN solo per riferirmi ai tipi in questione, poiché ho solo GCC 4.7.2 installato sulla mia macchina. –

Problemi correlati