我有一个std::set
,它允许从迭代器范围中推断。
我有一个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
的推断失败了呢?
我有一个std::set
,它允许从迭代器范围中推断。
我有一个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
的推断失败了呢?
只需使用当前的GCC版本(此时为8.0.0)进行构建即可。在旧版本的GCC标准库中似乎没有实现std::set
的模板推导指南。
std::set
迭代器构造函数的推导指南最近才被添加到 gcc HEAD。根据 GitHub 上的 gcc-mirror/gcc
,std::set
的迭代器构造函数的推导指南是在不到两周前被添加并合并到 libstdc++-v3的。
这就自然地解释了为什么早期版本的gcc(例如7.2.0)在使用迭代器构造函数时无法对模板参数进行推导。如果使用当前的gcc trunk(gcc HEAD 8.0.0 20171103 (experimental)),上述推导指南可用,并且迭代器构造函数的模板参数推导也将成功。(Extract from diff for
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
std::initializer_list
构造函数的模板参数推导已经成功(没有推导指南;该指南也是在上述提交中添加的),正如@JohnZwinck deleted answer中所解释的那样,这些构造函数本身并不是模板化的(不是由它们自己的模板参数列表参数化的),而是使用set
的成员类型value_type
——它只是set
的第一个模板类型参数Key
的typedef——作为模板参数传递给std::initializer
列表,我认为这会导致一个足够简单的推导路径,即使没有显式的推导指南也能成功。