Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the 'explicit' keyword allowing implicit conversions?

Tags:

c++

class Test {

    private:
    int value;

    public:
    void display(void)
    {
        cout << "Value [" << value << "]" << endl;
    }
    explicit Test(int i)
    {
        value=i;
    }   
};

int main() {

    Test a(5);
    Test b(4.9);

    a.display();
    b.display();

    cin.get();
    return 0;
}

Float value gets converted to int even though explicit is mentioned.

I was expecting (incorrectly) that float does not get converted to integer and object b not to be constructed.

like image 933
dpb Avatar asked Nov 14 '25 22:11

dpb


2 Answers

explicit refers to the constructor itself, not the constructor's parameters. Your explicit constructor may not be used as an implicit conversion to type Test.

void function( Test param );

function( 5 ); // Your "explicit" makes this call an error.
               // The parameter must be explicitly cast, such as Test(5)

In C++11 or later, you can prevent implicit parameter conversions using the = delete syntax on a template parameter.

  Test(int i)
  {
      value=i;
  }   

  template<typename T>
  Test(const T&) = delete;
  // ^ Aside from your int constructor and the implicitly-generated 
  // copy and move constructors, this will be a better match for any other type

In C++20 or later, you can prevent implicit parameter conversions using the std::same_as concept.

  Test(std::same_as<int> auto i)
  {
      value=i;
  }   
like image 69
Drew Dormann Avatar answered Nov 17 '25 12:11

Drew Dormann


explicit just prevents any implicit conversions. So if you had:

void foo(Test t);

You cannot call foo(4); because the Test constructor is explicit. You'd have to call foo(Test(4));. The explicit keyword has nothing to do with any conversions that might have to happen during construction.

From the standard [class.conv.ctor]:

An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used.

Which means that Test t = 4; is also illegal, but Test t(42.0) is fine.

like image 40
Barry Avatar answered Nov 17 '25 11:11

Barry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!