неполные типы с std :: map и std :: option - PullRequest
0 голосов
/ 29 мая 2018

Рассмотрим эту упрощенную и очень специфическую реализацию рекурсивного варианта поверх 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 является неполным типом.

Но ничто в стеке вызовов ошибок компилятора не указывает мне , почему нужно создать экземпляр 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 (т.е. добавление {}) решает проблему.Но с чего начинается проблема?

1 Ответ

0 голосов
/ 29 мая 2018

Обсуждаемая строка вызывает

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

Необходимость выполнения ADL для __get достаточно, чтобы вызвать создание экземпляров любого и всех связанных классов типа __vт. е. _Variant для поиска потенциальных функций-друзей (и шаблонов функций) с таким именем, определенным в этих классах.Это включает в себя pair, который сбил вас с толку.

...