具有std :: map和std :: variant的不完整类型 [英] incomplete types with std::map and std::variant

查看:114
本文介绍了具有std :: map和std :: variant的不完整类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑在std::variant之上对递归变量进行简化和非常具体的实现:

Consider this simplified and very specific implementation of a recursive variant on top of 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; 
}

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

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>需要实例化.顶行是:

But, nothing in the compiler error call-stack indicates to me why std::pair<const int, recursive_tag> needs to be instantiated. The top line there is:

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

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<...>>.

只需使recursive_tag完整(即通过添加{})即可解决此问题.但是是什么原因导致问题开始的呢?

Simply making recursive_tag complete (i.e. by adding {}) fixes the problem. But what causes the problem to begin with?

推荐答案

__get执行ADL的需求足以触发对__v类型(即_Variant)类型的任何和所有关联类的实例化,以查找与之相关的潜在朋友功能(和功能模板)这些类中定义的名称.其中包括pair使您绊倒.

The need to perform ADL for __get is sufficient to trigger instantiation of any and all associated classes of the type of __v, i.e., _Variant, to look for potential friend functions (and function templates) with that name defined within these classes. That includes the pair that tripped you up.

这篇关于具有std :: map和std :: variant的不完整类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆