Open CaseyCarter opened 7 years ago
I don't love the added complexity here. I would be ok with just picking T::value_type
over T::element_type
, with a de facto requirement that they be the same when they are both present.
I would be ok with just picking
T::value_type
overT::element_type
, with a de facto requirement that they be the same when they are both present.
I've included alternative wording for that formulation in the PR. (I have a mild preference to tell users they're making a mistake by defining conflicting value_type
and element_type
, we'll see what LWG has to say if and when we get around to discussing P4s.)
Many people have commented on the oddness of using
enable_if
in the specification ofvalue_type
in [iterator.assoc.types.value_type] (shown here after applying #299):The reason for the use of
enable_if
in e.g. theelement_type
case is simple to explain: we want this specialization to be used whenT
has a member typeelement_type
even if it specifies a non-object type so thatvalue_type_t<T>
is properly ambiguous for aT
that specifies bothelement_type
andvalue_type
. Nonetheless, many readers' first reaction is confusion: "I thought Concepts meant not having to useenable_if
anymore?!?" It would reduce reader confusion to eliminate the metaprogramming and use only associated constraints in the definition ofvalue_type
.Further, the specification of
value_type
is deliberately ambiguous when the typeT
has both a member typevalue_type
and a member typeelement_type
: the idea here is that the implementer ofT
should specializevalue_type
explicitly to disambiguate. I speculate that there is a sizable body of types in the wild with implementers that are confused about whether they should specifyvalue_type
orelement_type
that simply give up and specify both (e.g., the proposedspan
view which seems to think it's a container and a smart pointer). There's no reason thatvalue_type
should refuse to admit such types when thevalue_type
andelement_type
they specify are consistent.Finally, the text description of
value_type
is confused and redundant:value_type
class template may be specialized on user-defined types." normatively duplicates the allowance in the blanket wording in C++14 [namespace.std].I
such thatI::value_type
is valid and denotes a type,value_type<I>::type
names that type, unless it is not an object type..." and 5 "When instantiated with a typeI
such thatI::element_type
is valid and denotes a type,value_type<I>::type
names that type, unless it is not an object type..." redundantly specify requirements that are already explicit in the definition in para 1.Proposed Resolution
[Editor's note: This wording incorporates the PR of #299. We present two alternatives here: #1 ignores
element_type
whenvalue_type
is present, and #2 requires the two to be consistent when both are present.]Replace the specification of
value_type
in [iterator.assoc.types.value_type]/1 with:For alternative 1 (
value_type
takes precedence overelement_type
) further append:For alternative 2 (
value_type
andelement_type
must be consistent) instead append:For both alternatives, also replace paragraphs 3 through 5 with:
[Editor's note: Consider replacing uses of
I
in this section that refer to a type that potentially has an associated value type withT
. Use ofI
is appropriate for types that satisfyIterator
, butvalue_type
has applicability beyond models of iterator. ]