[英]Why does this template argument deduction fail on GCC but not Clang?
[英]Why does deduction fail for std::set in GCC?
我有一个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)即可构建。 std::set
的模板推导指南似乎没有在较旧的GCC版本的stdlib中实现。
std::set
的迭代器构造函数的推导指南最近才被添加到gcc HEAD中。 根据GitHub上的gcc-mirror/gcc
, std::set
的迭代器构造函数的演绎指南已添加并在不到两周前合并到libstdc ++ - v3 ,
(从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
这自然解释了为什么模板参数推导对于早期版本的gcc(例如7.2.0)的迭代器构造函数的模板set
失败了。 如果使用当前的gcc trunk( gcc HEAD 8.0.0 20171103(实验性) ) ,则可以使用上面的推论指南 ,并且对于迭代器构造函数,模板参数推导也是成功的。
至于为什么模板参数推导在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.