2017-09-30 38 views
13

Aşağıdaki kod:varyantları clang altında başarısız için <string> almak ++ ancak g ++

variant<string> x = "abc"; 
cout << get<string>(x) << "\n"; 

g altında çalışıyor ++ (sürüm 7.2). Ancak, ne zaman (sürüm 5.0) libstdc kullanarak ++ ++ clang altında derlenmiş, ben get yönteminde aşağıdaki hata olsun:

/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../include/c++/7.2.0/variant:238:46: fatal error: cannot cast 'std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >' to its private base class 'std::__detail::__variant::_Variant_storage<false, std:: 
__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >' 
     return __get(std::in_place_index<_Np>, std::forward<_Variant>(__v)._M_u); 

bu bir derleyici hata mı yoksa benim kod herhangi bir şekilde yasadışı?

+0

Standart kütüphane uygulaması olarak 'libC++' kullanılmalı mıdır? IIRC, clang libstdC++'yi varsayılan olarak kullanır. – StoryTeller

+0

Burada neyin yasadışı olduğunu göremiyorum, ancak, eğer öyleyse, bu çok basit bir şey berbat ... –

+2

Gcc + libstdC++ içinde çalıştığı göz önüne alındığında, clang + libC++ içinde çalışır, ancak clang + başarısız olur libstdC++, büyük olasılıkla, clang ve libstdC++ arasında ince bir uyumsuzluk olmasıdır. Cevap, uyumsuzluğun tam olarak ne olduğuna işaret etmelidir. – hvd

cevap

13

Bu kimin üreme Jonathan Wakely izniyle çok alakalı görünmelidir clang bug 31852 (ve ayrıca 33222), kaynaklanır:

template<typename V> auto get(V&) { } 

template<typename> 
class variant 
{ 
    template<typename V> friend auto get(V&); 
}; 

int main() 
{ 
    variant<int> v{}; 
    get(v); // error: ambiguous 
} 

clang düzgün tutucu türleri arkadaş bildirimleri tanımıyor. libstdC++ nasıl uyguladığını hangisi tam olarak std::get:

// Returns the typed storage for __v. 
template<size_t _Np, typename _Variant> 
constexpr decltype(auto) __get(_Variant&& __v) 
{ 
    return __get(std::in_place_index<_Np>, std::forward<_Variant>(__v)._M_u); 
} 

bu variant özel bir üyesini erişir, fakat bu fonksiyon properly declared a friend geçerli:

template<size_t _Np, typename _Vp> 
friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v); 

libstdC++ 'ın, çınlama sadece __get geçerli düşünmüyor edilir uygulaması olduğunu friend.

+2

Bilinen çözümler var mı? – papirrin

+1

En iyi ve makul derecede güvenli bir çözüm, geliştirme sırasında libstdC++ 'in değişken üstbilgi dosyasının değiştirilmiş bir sürümünü kullanmak olduğunu düşünüyorum. Değiştirmeniz gereken tek şey, arkadaş beyanını yorumlamak ve genel olarak __detail :: _ variant :: _ Variant_base (türetilmiş değişken depolamaya __get erişimini verir) türetmek. Bunu, GCC'yi birincil derleyici olarak kullanırken tonlarca bozukluğu hatalardan arındırmak için kullanıyorum ve herhangi bir yan etki görmedim. – Stacker