Подтвердить что ты не робот

Почему вывод не выполняется для std:: set в GCC?

У меня есть std::set, который позволяет выводить из диапазона итератора.

#include <iostream>
#include <set>

int main() 
{
   std::set s1 = {1,2,3,4}; 
   std::set s2(s1.begin(), s1.end());
}

Вышеуказанная программа не удалось скомпилировать в GCC.

Почему вывод std::set здесь отсутствует?

4b9b3361

Ответ 1

Просто возьмите текущую версию GCC (8.0.0 в это время), и она будет построена. Руководство по вычитанию шаблона для std::set просто не реализовано в старой версии stdlib для GCC.

Ответ 2

Гиды удаления для конструкторов итераторов std::set были добавлены только в gcc HEAD.

Согласно gcc-mirror/gcc в GitHub, директивы дедукции для конструктора итераторов std::set были добавлены и объединены в libstdС++ - v3 меньше двух недели назад,

(Извлечь из diff для libstdc++-v3/include/bits/stl_set.h)

 +#if __cpp_deduction_guides >= 201606
 +
 +  template<typename _InputIterator,
 +       typename _Compare =
 +         less<typename iterator_traits<_InputIterator>::value_type>,
 +       typename _Allocator =
 +         allocator<typename iterator_traits<_InputIterator>::value_type>,
 +       typename = _RequireInputIter<_InputIterator>,
 +       typename = _RequireAllocator<_Allocator>>
 +    set(_InputIterator, _InputIterator,
 +    _Compare = _Compare(), _Allocator = _Allocator())
 +    -> set<typename iterator_traits<_InputIterator>::value_type,
 +      _Compare, _Allocator>;
 +
 +  template<typename _Key, typename _Compare = less<_Key>,
 +       typename _Allocator = allocator<_Key>,
 +       typename = _RequireAllocator<_Allocator>>
 +    set(initializer_list<_Key>,
 +    _Compare = _Compare(), _Allocator = _Allocator())
 +    -> set<_Key, _Compare, _Allocator>;
 +
 +  template<typename _InputIterator, typename _Allocator,
 +       typename = _RequireInputIter<_InputIterator>,
 +       typename = _RequireAllocator<_Allocator>>
 +    set(_InputIterator, _InputIterator, _Allocator)
 +    -> set<typename iterator_traits<_InputIterator>::value_type,
 +       less<typename iterator_traits<_InputIterator>::value_type>,
 +       _Allocator>;
 +
 +  template<typename _Key, typename _Allocator,
 +       typename = _RequireAllocator<_Allocator>>
 +    set(initializer_list<_Key>, _Allocator)
 +    -> set<_Key, less<_Key>, _Allocator>;
 +
 +#endif

Это, естественно, объясняет, почему вывод шаблона шаблона терпит неудачу для шаблонов set конструкторами итераторов (s) для более ранних версий gcc, например. 7.2.0. Если используется текущая магистраль gcc (gcc HEAD 8.0.0 20171103 (экспериментальная)) доступны руководства по вычитанию выше, а вывод аргумента шаблона успешно также для конструкторов итераторов.

Что касается вывода аргумента шаблона в gcc 7.2.0 для конструкторов std::initializer_list (без указаний на вывод, которые также были добавлены в фиксации выше), что было несколько объяснено в @удаленный ответ JohnZwinck, эти конструкторы сами не замаскированы (не параметризованы их собственным списком параметров шаблона), но используйте set тип члена value_type - это просто typedef из set параметр первого шаблона Key - аргумент шаблона в список std::initializer, который я бы предположил, чтобы получить достаточно простой путь вычитания, чтобы преуспеть даже без и явного руководства по вычитанию.