This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++14 status.
Section: 23[containers]Status:C++14Submitter: Richard SmithOpened: 2012-10-04Last modified: 2017-07-05
Priority:1
View otheractive issues in [containers].
View all otherissues in [containers].
View all issues withC++14 status.
Discussion:
Most (all?) of the standard library containers have explicit default constructors. Consequently:
std::set<int> s1 = { 1, 2 }; // okstd::set<int> s2 = { 1 }; // okstd::set<int> s3 = {}; // ill-formed, copy-list-initialization selected an explicit constructor
Note that Clang + libc++ rejects the declaration ofs3
for this reason. This cannot possibly match the intent.
Suggested fix: apply this transformation throughout the standard library:
set() : set(Compare()) {}explicit set(const Compare& comp= Compare(), const Allocator& = Allocator());
[2012-10-06: Daniel adds concrete wording.]
[2012, Portland: Move to Open]
This may be an issue better solved by a core language tweak. Throw the issue over to EWG and see whether theybelieve the issue is better resolved in Core or Library.
AJM suggest we spawn a new status of 'EWG' to handle such issues - and will move this issue appropriately whenthe software can record such resolutions.
[2013-08-27, Joaquín M López Muñoz comments:]
For the record, I'd like to point out that the resolution proposed by the submitter, namely replacing
explicit basic_string(const Allocator& a = Allocator());
by
basic_string() : basic_string(Allocator()) {}explicit basic_string(const Allocator& a);
(and similarly for other container and container-like classes) might introduce a potentialbackwards-compatibility problem related with explicit instantiation. Consider for instance
struct my_allocator{ my_allocator(...); // no default ctor ...};template class std::basic_string<char, std::char_traits<char>, my_allocator<char>>;
This (which I understand is currently a valid explicit instantiation ofstd::basic_string
) will break ifstd::basic_string
ctors are modified as proposed by this issue, sincemy_allocator
doesn't havea default ctor.
[2013-10-06, Daniel comments:]
Issue2303(i) describes the more general problem related to explicit instantiation requests in the currentlibrary and may help to solve this problem here as well.
[2014-02-13, Issaquah, Jonathan revises wording]
Previous resolution from Daniel [SUPERSEDED]:
This wording is relative to N3376.
The more general criterion for performing the suggested transformation was: Any type with an initializer-list constructor that also has an explicit default constructor.
Change class template
basic_string
synopsis, 27.4.3[basic.string] p5 as indicated:basic_string() : basic_string(Allocator()) {}explicit basic_string(const Allocator& a= Allocator());Change 27.4.3.3[string.cons] before p1 as indicated:
explicit basic_string(const Allocator& a= Allocator());Change class template
deque
synopsis, 23.3.5.1[deque.overview] p2 as indicated:deque() : deque(Allocator()) {}explicit deque(const Allocator&= Allocator());Change 23.3.5.2[deque.cons] before p1 as indicated:
explicit deque(const Allocator&= Allocator());Change class template
forward_list
synopsis, [forwardlist.overview] p3 as indicated:forward_list() : forward_list(Allocator()) {}explicit forward_list(const Allocator&= Allocator());Change [forwardlist.cons] before p1 as indicated:
explicit forward_list(const Allocator&= Allocator());Change class template
list
synopsis, 23.3.11.1[list.overview] p2 as indicated:list() : list(Allocator()) {}explicit list(const Allocator&= Allocator());Change 23.3.11.2[list.cons] before p1 as indicated:
explicit list(const Allocator&= Allocator());Change class template
vector
synopsis, 23.3.13.1[vector.overview] p2 as indicated:vector() : vector(Allocator()) {}explicit vector(const Allocator&= Allocator());Change 23.3.13.2[vector.cons] before p1 as indicated:
explicit vector(const Allocator&= Allocator());Change class template specialization
vector<bool>
synopsis, 23.3.14[vector.bool] p1 as indicated:vector() : vector(Allocator()) {}explicit vector(const Allocator&= Allocator());Change class template
map
synopsis, 23.4.3.1[map.overview] p2 as indicated:map() : map(Compare()) {}explicit map(const Compare& comp= Compare(), const Allocator& = Allocator());Change 23.4.3.2[map.cons] before p1 as indicated:
explicit map(const Compare& comp= Compare(), const Allocator& = Allocator());Change class template
multimap
synopsis, 23.4.4.1[multimap.overview] p2 as indicated:multimap() : multimap(Compare()) {}explicit multimap(const Compare& comp= Compare(), const Allocator& = Allocator());Change 23.4.4.2[multimap.cons] before p1 as indicated:
explicit multimap(const Compare& comp= Compare(), const Allocator& = Allocator());Change class template
set
synopsis, 23.4.6.1[set.overview] p2 as indicated:set() : set(Compare()) {}explicit set(const Compare& comp= Compare(), const Allocator& = Allocator());Change 23.4.6.2[set.cons] before p1 as indicated:
explicit set(const Compare& comp= Compare(), const Allocator& = Allocator());Change class template
multiset
synopsis, 23.4.7.1[multiset.overview] p2 as indicated:multiset() : multiset(Compare()) {}explicit multiset(const Compare& comp= Compare(), const Allocator& = Allocator());Change 23.4.7.2[multiset.cons] before p1 as indicated:
explicit multiset(const Compare& comp= Compare(), const Allocator& = Allocator());Change class template
unordered_map
synopsis, 23.5.3.1[unord.map.overview] p3 as indicated:unordered_map() : unordered_map(see below) {}explicit unordered_map(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());Change 23.5.3.2[unord.map.cnstr] before p1 as indicated:
unordered_map() : unordered_map(see below) {}explicit unordered_map(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());Change class template
unordered_multimap
synopsis, 23.5.4.1[unord.multimap.overview] p3 as indicated:unordered_multimap() : unordered_multimap(see below) {}explicit unordered_multimap(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());Change 23.5.4.2[unord.multimap.cnstr] before p1 as indicated:
unordered_multimap() : unordered_multimap(see below) {}explicit unordered_multimap(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());Change class template
unordered_set
synopsis, 23.5.6.1[unord.set.overview] p3 as indicated:unordered_set() : unordered_set(see below) {}explicit unordered_set(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());Change 23.5.6.2[unord.set.cnstr] before p1 as indicated:
unordered_set() : unordered_set(see below) {}explicit unordered_set(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());Change class template
unordered_multiset
synopsis, 23.5.7.1[unord.multiset.overview] p3 as indicated:unordered_multiset() : unordered_multiset(see below) {}explicit unordered_multiset(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());Change 23.5.7.2[unord.multiset.cnstr] before p1 as indicated:
unordered_multiset() : unordered_multiset(see below) {}explicit unordered_multiset(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
[Issaquah 2014-02-11: Move to Immediate after final review]
Proposed resolution:
This wording is relative to N3376.
The more general criterion for performing the suggested transformation was: Any type with an initializer-list constructor that also has an explicit default constructor.
Change class templatebasic_string
synopsis, 27.4.3[basic.string] p5 as indicated:
basic_string() : basic_string(Allocator()) { }explicit basic_string(const Allocator& a= Allocator());
Change 27.4.3.3[string.cons] before p1 as indicated:
explicit basic_string(const Allocator& a= Allocator());
Change class templatedeque
synopsis, 23.3.5.1[deque.overview] p2 as indicated:
deque() : deque(Allocator()) { }explicit deque(const Allocator&= Allocator());
Change 23.3.5.2[deque.cons] before p1 as indicated:
explicit deque(const Allocator&= Allocator());
Change class templateforward_list
synopsis, [forwardlist.overview] p3 as indicated:
forward_list() : forward_list(Allocator()) { }explicit forward_list(const Allocator&= Allocator());
Change [forwardlist.cons] before p1 as indicated:
explicit forward_list(const Allocator&= Allocator());
Change class templatelist
synopsis, 23.3.11.1[list.overview] p2 as indicated:
list() : list(Allocator()) { }explicit list(const Allocator&= Allocator());
Change 23.3.11.2[list.cons] before p1 as indicated:
explicit list(const Allocator&= Allocator());
Change class templatevector
synopsis, 23.3.13.1[vector.overview] p2 as indicated:
vector() : vector(Allocator()) { }explicit vector(const Allocator&= Allocator());
Change 23.3.13.2[vector.cons] before p1 as indicated:
explicit vector(const Allocator&= Allocator());
Change class template specializationvector<bool>
synopsis, 23.3.14[vector.bool] p1 as indicated:
vector() : vector(Allocator()) { }explicit vector(const Allocator&= Allocator());
Change class templatemap
synopsis, 23.4.3.1[map.overview] p2 as indicated:
map() : map(Compare()) { }explicit map(const Compare& comp= Compare(), const Allocator& = Allocator());
Change 23.4.3.2[map.cons] before p1 as indicated:
explicit map(const Compare& comp= Compare(), const Allocator& = Allocator());
Change class templatemultimap
synopsis, 23.4.4.1[multimap.overview] p2 as indicated:
multimap() : multimap(Compare()) { }explicit multimap(const Compare& comp= Compare(), const Allocator& = Allocator());
Change 23.4.4.2[multimap.cons] before p1 as indicated:
explicit multimap(const Compare& comp= Compare(), const Allocator& = Allocator());
Change class templateset
synopsis, 23.4.6.1[set.overview] p2 as indicated:
set() : set(Compare()) { }explicit set(const Compare& comp= Compare(), const Allocator& = Allocator());
Change 23.4.6.2[set.cons] before p1 as indicated:
explicit set(const Compare& comp= Compare(), const Allocator& = Allocator());
Change class templatemultiset
synopsis, 23.4.7.1[multiset.overview] p2 as indicated:
multiset() : multiset(Compare()) { }explicit multiset(const Compare& comp= Compare(), const Allocator& = Allocator());
Change 23.4.7.2[multiset.cons] before p1 as indicated:
explicit multiset(const Compare& comp= Compare(), const Allocator& = Allocator());
Change class templateunordered_map
synopsis, 23.5.3.1[unord.map.overview] p3 as indicated:
unordered_map();explicit unordered_map(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Change 23.5.3.2[unord.map.cnstr] before p1 as indicated:
unordered_map() : unordered_map(size_type(see below)) { }explicit unordered_map(size_type n-1-Effects: Constructs an empty=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());unordered_map
using the specified hash function, key equality func-
tion, and allocator, and using at leastn buckets.Ifn is not provided,For the default constructor
the number of buckets is implementation-defined.max_load_factor()
returns 1.0.
Change class templateunordered_multimap
synopsis, 23.5.4.1[unord.multimap.overview] p3 as indicated:
unordered_multimap();explicit unordered_multimap(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Change 23.5.4.2[unord.multimap.cnstr] before p1 as indicated:
unordered_multimap() : unordered_multimap(size_type(see below)) { }explicit unordered_multimap(size_type n-1-Effects: Constructs an empty=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());unordered_multimap
using the specified hash function, key equality
function, and allocator, and using at leastn buckets.Ifn is not provided,For the default constructor
the number of buckets is implementation-defined.max_load_factor()
returns 1.0.
Change class templateunordered_set
synopsis, 23.5.6.1[unord.set.overview] p3 as indicated:
unordered_set();explicit unordered_set(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Change 23.5.6.2[unord.set.cnstr] before p1 as indicated:
unordered_set() : unordered_set(size_type(see below)) { }explicit unordered_set(size_type n-1-Effects: Constructs an empty=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());unordered_set
using the specified hash function, key equality func-
tion, and allocator, and using at leastn buckets.Ifn is not provided,For the default constructor
the number of buckets is implementation-defined.max_load_factor()
returns 1.0.
Change class templateunordered_multiset
synopsis, 23.5.7.1[unord.multiset.overview] p3 as indicated:
unordered_multiset();explicit unordered_multiset(size_type n=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Change 23.5.7.2[unord.multiset.cnstr] before p1 as indicated:
unordered_multiset() : unordered_multiset(size_type(see below)) { }explicit unordered_multiset(size_type n-1-Effects: Constructs an empty=see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());unordered_multiset
using the specified hash function, key equality
function, and allocator, and using at leastn buckets.Ifn is not provided,For the default constructor
the number of buckets is implementation-defined.max_load_factor()
returns 1.0.