为什么在GCC中std :: set的演绎失败?

时间:2017-11-06 12:53:03

标签: c++ gcc set c++17 template-deduction

我有std::set允许从迭代器范围中扣除。

#include <iostream>
#include <set>

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

GCC中的上述计划failed to compile

为什么此处std::set的扣减失败?

2 个答案:

答案 0 :(得分:21)

只需使用当前的GCC版本(此时为8.0.0)即可构建。 std::set的模板推导指南似乎没有在较旧的GCC版本的stdlib中实现。

答案 1 :(得分:1)

std::set的迭代器构造函数的推导指南最近才被添加到gcc HEAD。

根据GitHub的gcc-mirror/gccstd::set的迭代器构造函数的推导指南是added and merged to libstdc++-v3 less than two weeks ago

  

(从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

这自然解释了为什么模板参数推导对于早期版本的gcc的迭代器(s)构造函数的模板化set失败,例如: 7.2.0。如果使用当前的gcc trunk( gcc HEAD 8.0.0 20171103(experimental)the deduction guides above are available,则迭代器构造函数的模板参数推导也是成功的。

至于为什么模板参数推导已经在gcc 7.2.0中成功用于std::initializer_list构造函数(没有推导指南;也在上面的提交中添加了指南),正如在{{3这些构造函数本身不是模板化的(不是由它们自己的模板参数列表参数化),而是使用set的成员类型value_type - 这只是set'的typedef第一个模板类型参数Key - 作为std::initializer列表的模板参数,我认为即使没有明确的演绎指南,也可以在简单的演绎路径中取得成功。