I have a std::set
which allows deduction from an iterator range.
#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.
Why does deduction fail for std::set
here?
Just take the current GCC version (8.0.0 at this time) and it will build. The template deduction guide for std::set
just doesn't seem to be implemented in the older GCC version's stdlib.
std::set
was only recently added to 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 ,
(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
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. 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.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.