[英]incomplete types with std::map and std::variant
Consider this simplified and very specific implementation of a recursive variant on top of std::variant
: 考虑在
std::variant
之上的递归变体的这种简化且非常具体的实现:
#include <map>
#include <variant>
struct recursive_tag;
template <typename...>
struct RecursiveVariant;
template <>
struct RecursiveVariant<int, std::map<int, recursive_tag>>
: std::variant<int, std::map<int, RecursiveVariant<int, std::map<int, recursive_tag>>>>
{
using underlying = std::variant<int,
std::map<int, RecursiveVariant<int, std::map<int, recursive_tag>>>>;
using underlying::underlying;
};
int main() {
RecursiveVariant<int, std::map<int, recursive_tag>> rv;
}
This fails to compile on gcc 7/8 due to trying to instantiate std::pair<const int, recursive_tag>
, which itself fails because recursive_tag
is an incomplete type. 由于试图实例化
std::pair<const int, recursive_tag>
,因此无法在gcc 7/8上编译,因为recursive_tag
是一个不完整的类型,它本身也会失败。
But, nothing in the compiler error call-stack indicates to me why std::pair<const int, recursive_tag>
needs to be instantiated. 但是,编译器错误call-stack中没有任何内容告诉我为什么
std::pair<const int, recursive_tag>
需要实例化。 The top line there is: 最重要的是:
variant:252:48: required from '
void std::__detail::__variant::__erased_dtor(_Variant&&) [with _Variant = const std::__detail::__variant::_Variant_storage<false, int, std::map<int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > >, std::less<int>, std::allocator<std::pair<const int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > > > > > >&; long unsigned int _Np = 0]
变体:252:48:需要'
void std::__detail::__variant::__erased_dtor(_Variant&&) [with _Variant = const std::__detail::__variant::_Variant_storage<false, int, std::map<int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > >, std::less<int>, std::allocator<std::pair<const int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > > > > > >&; long unsigned int _Np = 0]
void std::__detail::__variant::__erased_dtor(_Variant&&) [with _Variant = const std::__detail::__variant::_Variant_storage<false, int, std::map<int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > >, std::less<int>, std::allocator<std::pair<const int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > > > > > >&; long unsigned int _Np = 0]
'void std::__detail::__variant::__erased_dtor(_Variant&&) [with _Variant = const std::__detail::__variant::_Variant_storage<false, int, std::map<int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > >, std::less<int>, std::allocator<std::pair<const int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > > > > > >&; long unsigned int _Np = 0]
'
pointing to: 指向:
249 template<typename _Variant, size_t _Np>
250 void
251 __erased_dtor(_Variant&& __v)
252 { std::_Destroy(std::__addressof(__get<_Np>(__v))); }
While type map<int, recursive_tag>
is spelled in there, the actual map
type that should be instantiated is map<int, RecursiveVariant<int, map<int, recursive_tag>>>
... which should only necessitate the instantiation of pair<const int, RecursiveVariant<...>>
. 虽然类型
map<int, recursive_tag>
在那里拼写,但应该实例化的实际map
类型是map<int, RecursiveVariant<int, map<int, recursive_tag>>>
...这应该只需要实例化pair<const int, RecursiveVariant<...>>
。
Simply making recursive_tag
complete (ie by adding {}
) fixes the problem. 简单地使
recursive_tag
完成(即添加{}
)可以解决问题。 But what causes the problem to begin with? 但是什么导致问题开始?
The line at issue calls 有争议的线路呼叫
std::_Destroy(std::__addressof(__get<_Np>(__v)));
The need to perform ADL for __get
is sufficient to trigger instantiation of any and all associated classes of the type of __v
, ie, _Variant
, to look for potential friend functions (and function templates) with that name defined within these classes. 为
__get
执行ADL的需要足以触发__v
类型的任何和所有相关类(即_Variant
,以查找具有在这些类中定义的该名称的潜在友元函数(和函数模板)。 That includes the pair
that tripped you up. 那包括绊倒你的那
pair
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.