Does C++11 standard require implementers to prioritize noexcept move constructor over const copy constructor for std::vector?

点点圈 提交于 2021-02-07 07:16:53

问题


Reading this and this and 23.3.6.5/1 of the standard, where in the latest C++ standard draft is it specified that implementers should prioritize the use of non-throwing move-constructor T(T &&t) noexcept over a const copy-constructor T(const T &t) when std::vector<T> re-allocates its element as a result of a push_back operation? Is it 13.3.3.1.4/1 on overload resolution of reference binding?

EDIT 1

I argue on 13.3.3.1.4/1 because of the following reasons:

  • 13.3/2

    Overload resolution selects the function to call in seven distinct contexts within the language. [...] invocation of a constructor for direct-initialization (8.5) of a class object (13.3.1.3); [...] Each of these contexts defines the set of candidate functions and the list of arguments in its own unique way. But, once the candidate functions and argument lists have been identified, the selection of the best function is the same in all cases: First, a subset of the candidate functions (those that have the proper number of arguments and meet certain other conditions) is selected to form a set of viable functions (13.3.2). Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed to match each argument to the corresponding parameter of each viable function.

  • 13.3.2/1

    From the set of candidate functions constructed for a given context (13.3.1), a set of viable functions is chosen, from which the best function will be selected by comparing argument conversion sequences for the best fit (13.3.3). The selection of viable functions considers relationships between arguments and function parameters other than the ranking of conversion sequences.

  • 13.3.1.3/1

    When objects of class type are direct-initialized (8.5), or copy-initialized from an expression of the same or a derived class type (8.5), overload resolution selects the constructor.

  • 13.3.3.1/5

    For the case where the parameter type is a reference, see 13.3.3.1.4.

  • 13.3.3.1.4/1

    When a parameter of reference type binds directly (8.5.3) to an argument expression, the implicit conversion sequence is the identity conversion, [...]

And therefore, I conclude that the requirement of identity conversion results in requiring the prioritization of T(T &&t) noexcept over T(const T &t). But, the other party I am arguing with is not convinced. So, I ask here.

EDIT 2

The following is the link between 23.3.6.5 and 13.3.3.1.4:

First, 23.3.6.5 requires the following of std::vector:

[...] void push_back(const T& x); void push_back(T&& x); Remarks: [...] If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T or by any InputIterator operation there are no effects. [...]

That is covered by 23.3.6.1/2 that requires the following:

A vector satisfies all of the requirements of a container and of a reversible container (given in two tables in 23.2), [...]

That is, std::vector is expected to comply with 23.2.1/7 that specifies the following:

Unless otherwise specified, all containers defined in this clause obtain memory using an allocator (see 17.6.3.5).

and with 23.2.1/3 that specifies the following:

For the components affected by this subclause that declare an allocator_type, objects stored in these components shall be constructed using the allocator_traits<allocator_type>::construct function and destroyed using the allocator_traits<allocator_type>::destroy function (20.7.8.2). These functions are called only for the container’s element type, not for internal types used by the container.

Since 20.7.8.2 specifies only one construct function as follows:

template <class T, class... Args>
static void construct(Alloc& a, T* p, Args&&... args);

with 20.7.8.2/5 requiring the following:

Effects: calls a.construct(p, std::forward<Args>(args)...) if that call is well-formed; otherwise, invokes ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...).

and 20.7.9.2/12 requiring the following of the default allocator:

Effects: ::new((void *)p) U(std::forward<Args>(args)...)

, both T(std::forward<Args>(args)...) in 20.7.8.2/5 and U(std::forward<Args>(args)...) in 20.7.9.2/12 will follow the constructor overload resolution requirement in 13.3.3.1.4/1.

The standard therefore requires the implementers to prioritize the use of move-constructor T(T &&t) noexcept over copy-constructor T(const T &t) when std::vector<T> re-allocates its elements due to push_back operations.

来源:https://stackoverflow.com/questions/46409188/does-c11-standard-require-implementers-to-prioritize-noexcept-move-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!