Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent undesired conversion in constructor

According to here, explicit:

Specifies constructors and conversion operators (since C++11) that don't allow implicit conversions or copy-initialization.

Thus, are these two techniques identical?

struct Z {
        // ...
        Z(long long);     // can initialize with a long long
        Z(long) = delete; // but not anything smaller
};

struct Z {
        // ...
        explicit Z(long long);     // can initialize ONLY with a long long
};
like image 681
johnbakers Avatar asked Apr 19 '16 14:04

johnbakers


People also ask

Which is keyword is used with constructors to prevent type conversion?

Explicit Keyword in C++ is used to mark constructors to not implicitly convert types in C++.

Which is true about conversion constructor?

In C++, if a class has a constructor which can be called with a single argument, then this constructor becomes conversion constructor because such a constructor allows automatic conversion to the class being constructed.

What is a type conversion constructor?

A conversion constructor is a single-parameter constructor that is declared without the function specifier explicit . The compiler uses conversion constructors to convert objects from the type of the first parameter to the type of the conversion constructor's class.


1 Answers

No, they're not the same. explicit disallows implicit conversions to that type if that constructor is selected - implicit conversions in arguments don't matter. delete disallows any construction if that constructor is selected, and can be used to disallow implicit argument conversion.

So for instance:

struct X {
    explicit X(int ) { }
};

void foo(X ) { }

foo(4);      // error, because X's constructor is explicit
foo(X{3});   // ok
foo(X{'3'}); // ok, this conversion is fine

That is separate from deleteing a constructor:

struct Y {
    Y(int ) { }
    Y(char ) = delete;
};

void bar(Y ) { }

bar(4);      // ok, implicit conversion to Y since this constructor isn't explicit
bar('4');    // error, this constructor is deleted
bar(Y{'4'}); // error, doesn't matter that we're explicit

The two techniques are also orthogonal. If you want a type to not be implicitly-convertible and only constructible from exactly an int, you can do both:

struct W {
    explicit W(int ) { }

    template <class T>
    W(T ) = delete;
};

void quux(W );

quux(4);      // error, constructor is explicit
quux('4');    // error, constructor is deleted
quux(4L);     // error, constructor is deleted
quux(W{'4'}); // error, constructor is deleted
quux(W{5});   // ok
like image 181
Barry Avatar answered Sep 19 '22 06:09

Barry