Default argument and empty list initialization
Asked Answered
C

1

5

Consider the following code, of a simple class with a constructor taking an argument with a default value.

// 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;
}

Are the two versions of the constructor equivalent (will always produce the same result for any T), or they are different?

If they are different, could you provide an example of T for which the two would lead to different results?

Committee answered 15/8, 2018 at 9:49 Comment(1)
why so verbose? Do i miss something or is the question basically about the difference between T t = {}; and T t = T(); ?Guyenne
A
7

No, they are not equivalent. Second variant relies on implicitness of T's default constructor:

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

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

Also I think it is not a good idea to call a copy constructor from a temporary instead of calling a default constructor without a temporary. That is it would be better to implement separate constructors:

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

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

    type value;
};
Addington answered 15/8, 2018 at 9:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.