c++initializationstdconstexpr

How is std::vector able to be constexpr without constexpr std::uninitialized_copy?


I am implementing my own container and I was trying to make it as much constexpr friendly as possible.

In the process I found out that std::uninitialized_copy is not constexpr and therefore I can't implement copy assignment using the standard algorithms.

However, std::vector is constexpr friendly:

constexpr auto f() {
    std::vector<int> v = {1, 2, 3};
    return v.size();
}

static_assert(f() == 3);

I can't achieve this when I replace std::vector by my own container. I get the error:

... error: call to non-‘constexpr’ function ‘_ForwardIterator std::uninitialized_copy(_InputIterator, ...

I wonder how the standard library (e.g. stdlib) can implement that. Does it use a secret implementation of uninitialized_copy that is constexpr? Is a constexpr uninitalized_copy implementable at all?

I guess the challenge is to have constexpr addressof and constexpr construct_at. Is there an implementation that I can fallback into?


Solution

  • std::vector doesn't use std::uninitialized_copy. It calls std::allocator_traits::construct to perform copy construction. The latter defaults to calling std::construct_at, which is handled specially during constant evaluation ([expr.const]/6).

    In practice, compilers treats std::construct_at specially, so that it can use placement new during constant evaluation.