[英]Why does deduction fail for std::set in GCC?
I have a std::set
which allows deduction from an iterator range. 我有一个std::set
,它允许从迭代器范围中扣除。
#include <iostream>
#include <set>
int main()
{
std::set s1 = {1,2,3,4};
std::set s2(s1.begin(), s1.end());
}
The above program failed to compile in GCC. 上述程序未能在GCC中编译。
Why does deduction fail for std::set
here? 为什么std::set
演绎失败?
Just take the current GCC version (8.0.0 at this time) and it will build. 只需采用当前的GCC版本(此时为8.0.0)即可构建。 The template deduction guide for std::set
just doesn't seem to be implemented in the older GCC version's stdlib. std::set
的模板推导指南似乎没有在较旧的GCC版本的stdlib中实现。
std::set
was only recently added to gcc HEAD. std::set
的迭代器构造函数的推导指南最近才被添加到gcc HEAD中。 According to gcc-mirror/gcc
at GitHub, the deduction guides for std::set
's iterators constructor(s) was added and merged to libstdc++-v3 less than two weeks ago , 根据GitHub上的gcc-mirror/gcc
, std::set
的迭代器构造函数的演绎指南已添加并在不到两周前合并到libstdc ++ - v3 ,
(Extract from diff for
libstdc++-v3/include/bits/stl_set.h
) (从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
This naturally explains why template argument deduction fails for the templated set
by iterator(s) constructors for earlier versions of gcc, eg 7.2.0. 这自然解释了为什么模板参数推导对于早期版本的gcc(例如7.2.0)的迭代器构造函数的模板set
失败了。 If using the current gcc trunk ( gcc HEAD 8.0.0 20171103 (experimental) ) the deduction guides above are available , and the template argument deduction is successful also for the iterator(s) constructors. 如果使用当前的gcc trunk( gcc HEAD 8.0.0 20171103(实验性) ) ,则可以使用上面的推论指南 ,并且对于迭代器构造函数,模板参数推导也是成功的。
As for why the template argument deduction is successful already in gcc 7.2.0 for the std::initializer_list
constructors (without deduction guides; guides that was also added in the commit above), as was somewhat explained in @JohnZwinck deleted answer , these constructors are not templated themselves (not parameterized by their own template parameter list), but use set
's member type value_type
—which is simply a typedef of the set
's first template type parameter Key
—as template argument to the std::initializer
list, which I would assume results in a simple enough deduction path to succeed even without and explicit deduction guide. 至于为什么模板参数推导在gcc 7.2.0中已经成功用于std::initializer_list
构造函数(没有推导指南;也在上面的提交中添加了指南),正如在@JohnZwinck删除的答案中有所解释的那样 ,这些构造函数不是自己模板化的(不是由他们自己的模板参数列表参数化),而是使用set
的成员类型value_type
-which只是set
的第一个模板类型参数的typedef Key
-as std::initializer
list的模板参数,即使没有明确的演绎指南,我认为这会导致一个简单的演绎路径成功。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.