I have a simple class 'A' with the following contents:
class A {
public:
struct data_t {
int32_t val;
data_t(int32_t _val) :
val(_val) {
;
};
};
A& operator << (const data_t &data) {
printf("[%s] %d\n", __func__, data.val);
return *this;
};
void func(const data_t &data) {
printf("[%s] %d\n", __func__, data.val);
}
};
I tried the following codes and got:
A a;
a<<{100}; //"expected primary-expression before ‘{’ token"
a<<A::data_t{100}; //OK.
a.func({100}); //OK.
Why a<<{100}; is NG and a.func({100}); is OK?
I don't want to use the second sentence because it is too long and complicated to read.
CodePudding user response:
Since A::data_t
has a conversion constructor (a non-explicit single-argument constructor) the compiler can do implicit conversions from int32_t
to A::data_t
.
That means you can simply do e.g.
a << 100;
CodePudding user response:
Why a<<{100}; is NG and a.func({100}); is OK?
The grammar of the language simply only allows braced initializer lists in certain places. As operand to (arithmetic) operators in expressions it is generally not allowed, even thought one might be able to make sense of it for overloaded operators.
Braced initializer lists are potentially allowed:
- in initializers of variables, class members,
new
expressions, default arguments (for function parameters and non-type template parameters) - after a type specifier (functional type conversion notation)
- as arguments in function calls and template arguments
- as right-hand side of assignment
- as operand to
return
,co_return
andco_yield
- as initializer in a range-
for
Assuming I didn't forget any case, they cannot be used anywhere else.