简体   繁体   English

std :: map和std :: variant的不完整类型

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM