Reputation: 60381
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?
Upvotes: 5
Views: 358
Reputation: 37549
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;
};
Upvotes: 7