1
struct Foo {
    int val;
    Foo() : val(-1) {}
    explicit Foo(int val_) : val(val_) {}
    Foo& operator=(int val_) { val = val_; return *this; } 
    operator int () const { return val; }
};

int main()
{
    Foo foo = 1; // error
    Foo foo2;
    foo2 = 2; // works fine
    return 0;
}

error: conversion from 'int' to non-scalar type 'Foo' requested
     Foo foo = 1;

The code should be self-explanatory. I would like to understand why the direct assignment is illegal when a suitable assignment operator has been defined.

MarkB
  • 672
  • 2
  • 9

1 Answers1

2

Unlike foo2 = 2;, Foo foo = 1; is not assignment, but initialization. Only constructors would be considered (to construct foo). The appropriate constructor Foo::Foo(int) is marked as explicit then can't be used in copy initialization like Foo foo = 1;.

If you make Foo::Foo(int) non-explicit then the code would work; direct initialization (which considers explicit constructor) like Foo foo(1); works too.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • I understand the error message. I'm hoping to get more insight as to *why* this is the case. Put another way, what would go wrong if the C++ language (and compilers) supported this code? ...or maybe what I really am asking for is implicit construction. – MarkB Jan 05 '22 at 14:33
  • @MarkB This is syntax. You're using initialization syntax; why are you hoping assignment should be performed? – songyuanyao Jan 05 '22 at 14:38
  • @MarkB when you go out of your way to opt-out of allowing implicit conversions, it _is_ supporting your code by not compiling. If you want implicit conversions enabled, don't mark it `explicit`, BUT implicit conversions are a common source of errors so don't be too quick to embrace them. I prefer `explicit` constructors most of the time. – Chris Uzdavinis Jan 05 '22 at 14:42