2013-06-02 6 views
5

Podczas kodowania wokół w projekcie pracuję nad odkryłem coś naprawdę dziwne:dlaczego nie można rozwiązać przy użyciu GCC oświadczenie do właściwego rodzaju

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()); 
} 

Najdziwniejsze o tym, że kod jest tag zostaje rozstrzygnięty na nazwa_tagi :: call_with_traits :: tag;, ale no_tag błędy OUT:

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

chociaż powinno odnosić się do tej samej deklaracji, używając w tym samym struktury. Czy jest coś, czego mi brakuje, czy jest to jakiś błąd w GCC?

A live example can be found here, w tym powiązany komunikat o błędzie z GCC.

+1

Powiedziałbym, że to błąd. Kompiluje się dobrze na GCC 4.8.0 i na Clangu 3.2 –

Odpowiedz

6

To wygląda na błąd w g ++ 4.7.2. Oto minimalne przykład:

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

Brak błędy jeśli typedef jest używany zamiast deklaracji using, lub jeśli używasz A<int> zamiast A<T>.

+0

Andy Prowl już to zasugerował, ale dziękuję za weryfikację. Na razie po prostu użyję FQN, aby odnieść się do typów, o których mowa, ponieważ mam tylko GCC 4.7.2 zainstalowany na moim komputerze. –

Powiązane problemy