我有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
的扣减失败?
答案 0 :(得分:21)
只需使用当前的GCC版本(此时为8.0.0)即可构建。 std::set
的模板推导指南似乎没有在较旧的GCC版本的stdlib中实现。
答案 1 :(得分:1)
std::set
的迭代器构造函数的推导指南最近才被添加到gcc HEAD。根据GitHub的gcc-mirror/gcc
,std::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
列表的模板参数,我认为即使没有明确的演绎指南,也可以在简单的演绎路径中取得成功。