2017-09-30 20 views
13

Các mã sau đây:được <string> cho các biến thể thất bại dưới kêu vang ++ nhưng không g ++

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

hoạt động tốt dưới g ++ (phiên bản 7.2). Tuy nhiên, khi biên soạn dưới kêu vang ++ (phiên bản 5.0) sử dụng libstdC++, tôi nhận được lỗi sau trong phương pháp get:

/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); 

Đây có phải là một lỗi biên dịch, hoặc là mã của tôi là bất hợp pháp bằng cách nào?

+0

Bạn có chỉ định rằng 'libC++' nên được sử dụng làm thư viện chuẩn không? IIRC, clang sử dụng libstdC++ theo mặc định. – StoryTeller

+0

Tôi không thể thấy những gì là bất hợp pháp ở đây, nhưng, nếu vậy, điều này sẽ là một điều khá cơ bản để mess up ... –

+2

Cho rằng nó hoạt động trong gcc + libstdC++, hoạt động trong clang + libC++, nhưng thất bại trong clang + libstdC++, trường hợp có khả năng nhất là nó là một sự không tương thích tinh tế giữa clang và libstdC++. Một câu trả lời nên chỉ ra chính xác những gì không tương thích là mặc dù. – hvd

Trả lời

13

này là do clang bug 31852 (và cũng 33222), mà biếu không của Jonathan Wakely sinh sản nên trông rất có liên quan:

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 
} 

kêu vang không công nhận đúng khai báo bạn rằng có các loại placeholder. Đó là chính xác có bao libstdC++ xây dựng 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); 
} 

này truy cập một thành viên tư nhân variant, nhưng chức năng này là properly declared a friend:

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

libstdC++ 's thực hiện được hợp lệ, kêu vang chỉ không nghĩ __get là một friend.

+2

Bất kỳ cách giải quyết nào không? – papirrin

+1

Tôi nghĩ cách giải quyết tốt nhất và hợp lý là sử dụng phiên bản sửa đổi của tập tin tiêu đề biến thể libstdC++ trong quá trình phát triển. Tất cả những gì bạn cần thay đổi là nhận xét ra tuyên bố kết bạn và công khai xuất phát từ __detail :: _ variant :: _ Variant_base (cho phép truy cập __get vào bộ nhớ biến thể cơ bản). Tôi sử dụng điều này để im lặng tấn lỗi từ clang-gọn gàng trong khi sử dụng GCC như trình biên dịch chính và đã không nhận thấy bất kỳ tác dụng phụ xấu. – Stacker

Các vấn đề liên quan