Ответ 1
Это вызвано clang bug 31852 (а также 33222), репродукция любезности Джонатана Вакели должна выглядеть очень актуальной:
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 неправильно распознает объявления друзей, которые имеют типы заполнителей. Именно так libstdС++ реализует 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);
}
он обращается к частному члену variant
, но эта функция правильно объявлена friend
:
template<size_t _Np, typename _Vp>
friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v);
реализация libstdС++ действительна, clang просто не думает, что __get
является friend
.