具有std :: map和std :: variant的不完整类型 [英] incomplete types with std::map and 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屋!