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, e.g. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With