Конструкторы: разница между дефолтом и делегированием параметра

Сегодня я наткнулся на эти стандартные объявления конструкторов std::vector:

// until C++14
explicit vector( const Allocator& alloc = Allocator() );
// since C++14
vector() : vector( Allocator() ) {}
explicit vector( const Allocator& alloc );

Это изменение можно увидеть в большинстве стандартных контейнеров. Немного другой пример: std::set:

// until C++14
explicit set( const Compare& comp = Compare(),
              const Allocator& alloc = Allocator() );
// since C++14
set() : set( Compare() ) {}
explicit set( const Compare& comp,
              const Allocator& alloc = Allocator() );

В чем разница между двумя шаблонами и каковы их преимущества? Являются ли они строго эквивалентными - компилятор генерирует нечто подобное второму из первого?

Ответы

Ответ 1

Отличие состоит в том, что

explicit vector( const Allocator& alloc = Allocator() );

является explicit даже для случая, когда используется аргумент по умолчанию, а

vector() : vector( Allocator() ) {}

нет. (explicit в первом случае необходимо, чтобы Allocator неявно был конвертирован в vector.)

Это означает, что вы можете написать

std::vector<int> f() { return {}; }

или

std::vector<int> vec = {};

во втором случае, но не в первом.

См. LWG-выпуск 2193.