This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 2303. Explicit instantiation of `std::vector<UserType>` broken?

Section: 17.7.3.4 [new.delete.placement] Status: New Submitter: Daniel Krügler Opened: 2013-09-18 Last modified: 2016-01-28

Priority: 3

View all other issues in [new.delete.placement].

View all issues with New status.

Discussion:

The library gives explicit permission in 16.4.5.2.1 [namespace.std] p2 that user code may explicitly instantiate a library template provided that the instantiations depend on at least one user-defined type:

> A program may explicitly instantiate a template defined in the standard library only if the declaration depends on the name of a user-defined type and the instantiation meets the standard library requirements for the original template.

But it seems that the C++11 library is not specified in a way that guarantees such an instantiation to be well-formed if the minimum requirements of the library is not satisfied.

For example, in general, the first template parameter of `std::vector` is not required to be `DefaultConstructible` in general, but due to the split of the single C++03 member function with default argument

>     void resize(size_type sz, T c = T());

into

>     void resize(size_type sz);
>     void resize(size_type sz, const T& c);

the effect is now that for a type `ND` that is not `DefaultConstructible`, such as

>     struct NP {
>       NP(int);
>     };

the explicit instantiation of `std::vector<ND>` is no longer well-formed, because the attempt to instantiate the single-argument overload of `resize` cannot not succeed, because this function imposes the `DefaultInsertable` requirements and given the default allocator this effectively requires `DefaultConstructible`.

But `DefaultConstructible` is not the only point, what about `CopyConstructible` versus `MoveConstructible` alone? It turns out that currently the second `resize` overload would fail during an explicit instantiation for a type like

>     struct MO {
>       MO() = default;
>       MO(MO&&) = default;
>     };

because it imposes `CopyInsertable` requirements that end up being equivalent to the `CopyConstructible` requirements for the default allocator.

Technically a library can solve these issues: For special member functions by defining them in some base class, for others by transforming them effectively into a function template due to the great feature of default template arguments for function templates (At the very moment the validity of the latter approach depends on a resolution of core language issue CWG 1635, though). E.g. the here mentioned `resize` functions of `std::vector` could be prevented from instantiation by defining them like this with an implementation:

>     template<class = void>
>     void resize(size_type sz) { […] }
>     template<class = void>
>     void resize(size_type sz, const T& c) { […] }

In this case, these functions could also be defined in a base class, but the latter approach won't work in all cases.

Basically such an implementation is required to constrain all member functions that are not covered by the general requirements imposed on the actual library template parameters. I tested three different C++11 library implementations and but none could instantiate for example `std::list`, `std::vector`, or `std::deque` with value types that are not `DefaultConstructible` or only `MoveConstructible`.

This issue is raised to clarify the current situation in regard to the actual requirements imposed on user-provided types that are used to explicitly instantiate Library-provided templates. For example, the current Container requirements impose very little requirements on the actual value type and it is unclear to which extend library implementations have to respect that.

The minimum solution of this issue should be to at least realize that there is no fundamental requirement on `DefaultConstructible` for value types of library containers, because we have since C++03 the general statement of 16.4.4.2 [utility.arg.requirements] ("In general, a default constructor is not required."). It is unclear whether `CopyConstructible` should be required for an explicit instantiation request, but given the careful introduction of move operations in the library it would seem astonishing that a `MoveConstructible` type wouldn't suffice for value types of the container types.

In any case I can envision at least two approaches to solve this issue:

1. As indicated in LWG 2292, those function could get an explicit "Template Constraints:" element, albeit this promises more than needed to solve this issue.

2. The library could introduce a completely new element form, such as "Instantiation Constraints:" that would handle this situation for explicit instantiation situations. This would allow for simpler techniques to solve the issue when explicit instantiation is required compared to the first bullet, because it would not (necessarily) guarantee SFINAE-friendly expression-wellformedness, such as inspecting the expression `std::declval<std::vector<ND>&>.resize(0)` in an unevaluated context.

It should be noted that the 2013-08-27 comment to LWG 2193 could be resolved by a similar solution as indicated in this issue here.

Proposed resolution: