为什么在GCC中,对于std::set而言,扣除操作失败?

14

我有一个std::set,它允许从迭代器范围中推断。

Translated:

我有一个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的推断失败了呢?


8
C++17新增了类模板参数推导的功能。问题是为什么迭代器构造函数没有实现这个功能。 - Quentin
2
@Ron,它在标签中 :) - Quentin
2
根据GCC功能矩阵,类模板的模板参数推导应该在版本7中实现。 - YSC
@YSC 矩阵显示核心特性。它可以在gcc7中工作(s1初始化编译)。 - n. m.
2个回答

20

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


1

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

根据 GitHub 上的 gcc-mirror/gccstd::set 的迭代器构造函数的推导指南是在不到两周前被添加并合并到 libstdc++-v3的。

(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
这就自然地解释了为什么早期版本的gcc(例如7.2.0)在使用迭代器构造函数时无法对模板参数进行推导。如果使用当前的gcc trunk(gcc HEAD 8.0.0 20171103 (experimental)),上述推导指南可用,并且迭代器构造函数的模板参数推导也将成功。
关于为什么在gcc 7.2.0中std::initializer_list构造函数的模板参数推导已经成功(没有推导指南;该指南也是在上述提交中添加的),正如@JohnZwinck deleted answer中所解释的那样,这些构造函数本身并不是模板化的(不是由它们自己的模板参数列表参数化的),而是使用set的成员类型value_type——它只是set的第一个模板类型参数Key的typedef——作为模板参数传递给std::initializer列表,我认为这会导致一个足够简单的推导路径,即使没有显式的推导指南也能成功。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接