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

2023-12-19

考虑这个简化且非常具体的递归变体实现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; 
}

由于尝试实例化,这无法在 gcc 7/8 上编译std::pair<const int, recursive_tag>,它本身失败了,因为recursive_tag是一个不完整的类型。

但是,编译器错误调用堆栈中没有任何内容向我表明why std::pair<const int, recursive_tag>需要实例化。最上面一行是:

变体: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]

指向:

249   template<typename _Variant, size_t _Np>
250     void
251     __erased_dtor(_Variant&& __v)
252     { std::_Destroy(std::__addressof(__get<_Np>(__v))); }

同时键入map<int, recursive_tag>那里写的是实际的map应该实例化的类型是map<int, RecursiveVariant<int, map<int, recursive_tag>>>...这应该只需要实例化pair<const int, RecursiveVariant<...>>.

简单制作recursive_tag完成(即通过添加{})解决了问题。但问题的根源是什么?


The 有问题的线路 https://github.com/gcc-mirror/gcc/blob/8bc5c186d9e5d83cdf9619483e60294ffb7bf630/libstdc%2B%2B-v3/include/std/variant#L252 calls

std::_Destroy(std::__addressof(__get<_Np>(__v)));

需要执行 ADL__get足以触发该类型的任何和所有关联类的实例化__v, i.e., _Variant,查找在这些类中定义的具有该名称的潜在友元函数(和函数模板)。这包括pair那让你绊倒了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::map 和 std::variant 的不完整类型 的相关文章

随机推荐