Аргумент по умолчанию и инициализация пустого списка

Рассмотрим следующий код простого класса с конструктором, принимающим аргумент со значением по умолчанию.

// Version 1
template <class T>
struct object1 {
    using type = T;
    constexpr object1(const type& val = type()): value(val) {}
    type value;
};

// Version 2
template <class T>
struct object2 {
    using type = T;
    constexpr object2(const type& val = {}): value(val) {}
    type value;
};

// Main
int main(int argc, char* argv[]) {
    using type = /* Something */;
    object1<type> x1;
    object2<type> x2;
    auto value1 = x1.value;
    auto value2 = x2.value;
    // Is there certain types for which value1 and value2 will be different?
    return 0;
}

Являются ли две версии конструктора эквивалентными (всегда будут давать один и тот же результат для любого T) или они разные?

Если они разные, не могли бы вы привести пример T, для которого они привели бы к разным результатам?


person Vincent    schedule 15.08.2018    source источник
comment
зачем так многословно? Я что-то упустил или вопрос в основном о разнице между T t = {}; и T t = T();?   -  person 463035818_is_not_a_number    schedule 15.08.2018


Ответы (1)


Нет, они не эквивалентны. Второй вариант основан на неявности конструктора T по умолчанию:

class foo
{
   public: explicit foo() {}
};

object1<foo> of{}; // ok
object2<foo> of{}; // error

Также я думаю, что не стоит вызывать конструктор копирования из временного вместо вызова конструктора по умолчанию без временного. То есть было бы лучше реализовать отдельные конструкторы:

template <class T>
struct object1 {
    using type = T;
    constexpr object1(void): value{} {}

    constexpr object1(const type& val): value{val} {}

    type value;
};
person user7860670    schedule 15.08.2018