dynarray constructor ambiguitySection: 99 [arrays.ts::dynarray.cons] Status: NAD Arrays Submitter: Jonathan Wakely Opened: 2013-04-23 Last modified: 2016-03-08
Priority: 0
View all issues with NAD Arrays status.
Discussion:
Addresses: arrays.ts
These constructors can interact badly::
template<class Alloc> dynarray(size_type c, const Alloc& alloc); dynarray(size_type c, const T& v);
Unless the second argument is a value of exactly the type T you will get the first constructor, i.e. 
all of these will fail to compile:
dynarray<long> dlong(1, 1); // 1 is not long dynarray<float> dflt(1, 1.0); // 1.0 is not float dynarray<int*> dptr(1, nullptr); // nullptr is not int* dynarray<void*> doh(1, 0); // 0 is not void*
The nullptr case is particularly annoying, a user trying to do the right thing by saying nullptr 
instead of NULL still gets the wrong result.
Alloc shall meet the requirements for an Allocator" 
but doesn't actually say "shall not participate in overload resolution unless ..."
I believe we have no precedent for using SFINAE to check "the requirements for an Allocator" because it's 
a pretty complicated set of requirements. We could say it shall not participate in overload resolution if Alloc 
is implicitly convertible to value_type.
Alternatively, we could follow the same approach used by other types that can be constructed with an unconstrained 
allocator type and use std::allocator_arg_t as the first argument instead of adding an allocator after the 
other arguments.
[2013-09 Chicago:]
Move to Deferred. This feature will ship after C++14 and should be revisited then.
[2014-06-06 pre-Rapperswil]
This issue has been reopened as arrays-ts.
[2014-06-16 Rapperswil]
Move to Ready for alternative A
Previous resolution [SUPERSEDED]:
Either use the correct way to unambiguously call a constructor taking any type of allocator, i.e. change the constructors to take
dynarray(std::allocator_arg_t, const Alloc&, ...)by modifying both the synopsis 99 [arrays.ts::dynarray.overview] p2 and 99 [arrays.ts::dynarray.cons] before p9 like so:template <class Alloc> dynarray(allocator_arg_t, const Alloc& a, size_type c, const Alloc& alloc); template <class Alloc> dynarray(allocator_arg_t, const Alloc& a, size_type c, const T& v, const Alloc& alloc); template <class Alloc> dynarray(allocator_arg_t, const Alloc& a, const dynarray& d, const Alloc& alloc); template <class Alloc> dynarray(allocator_arg_t, const Alloc& a, initializer_list<T>, const Alloc& alloc);or constrain the problematic constructor by adding a new paragraph to 99 [arrays.ts::dynarray.cons]:
template <class Alloc> dynarray(size_type c, const Alloc& alloc); template <class Alloc> dynarray(size_type c, const T& v, const Alloc& alloc); template <class Alloc> dynarray(const dynarray& d, const Alloc& alloc); template <class Alloc> dynarray(initializer_list<T>, const Alloc& alloc);-9- Requires:
-10- Effects: Equivalent to the preceding constructors except that each element is constructed with uses-allocator construction (20.2.8.2 [allocator.uses.construction]). -?- Remarks: The first constructor shall not participate in overload resolution unlessAllocshall meet the requirements for an Allocator (16.4.4.6 [allocator.requirements]).Allocis not implicitly convertible toT.
[2014/11 Urbana]
Held at Ready status, pending clarification of Arrays TS
Proposed resolution:
Use the correct way to unambiguously call a constructor taking any type of allocator, i.e. change the 
constructors to take dynarray(std::allocator_arg_t, const Alloc&, ...) by modifying both the synopsis
99 [arrays.ts::dynarray.overview] p2 and 99 [arrays.ts::dynarray.cons] before p9 like so:
template <class Alloc> dynarray(allocator_arg_t, const Alloc& a, size_type c, const Alloc& alloc); template <class Alloc> dynarray(allocator_arg_t, const Alloc& a, size_type c, const T& v, const Alloc& alloc); template <class Alloc> dynarray(allocator_arg_t, const Alloc& a, const dynarray& d, const Alloc& alloc); template <class Alloc> dynarray(allocator_arg_t, const Alloc& a, initializer_list<T>, const Alloc& alloc);