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

Bar*_*rry 14 c++ libstdc++ incomplete-type c++17

考虑这种简化且非常具体的递归变体实现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; 
}
Run Code Online (Sandbox Code Playgroud)

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

但是,编译器错误call-stack中没有任何内容向我指出为什么 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))); }
Run Code Online (Sandbox Code Playgroud)

虽然类型map<int, recursive_tag>拼写在那里,但map应该实例化的实际类型是map<int, RecursiveVariant<int, map<int, recursive_tag>>>......这应该只需要实例化pair<const int, RecursiveVariant<...>>.

简单地recursive_tag完成(即通过添加{})修复问题.但是什么导致问题开始?

T.C*_*.C. 14

有争议线路呼叫

std::_Destroy(std::__addressof(__get<_Np>(__v)));
Run Code Online (Sandbox Code Playgroud)

执行ADL的需要__get足以触发该类型的任何和所有相关类的实例化__v,即,_Variant寻找具有在这些类中定义的该名称的潜在朋友函数(和函数模板).那包括pair绊倒了你.

  • 唉,那个文件中对该函数的调用还有多少.我相信新的一夜之间就会出现. (5认同)