In the C language the name of a structured type S
ist struct S
.
In C++ one can also use struct S
as typename instead of S
as usual for
struct S {};
struct S s1; // also ok in C++
S s2; // normal way in C++
So, the assumption is, that using struct S
or S
as typename in C++ is a matter of taste ;-)
But in the following example there are places where struct S
is not allowed:
struct S1 {
S1(int x = 0) : x{x} {}
int x{};
};
typedef S1 S2;
template<typename T>
auto foo(T a) {
// T::_; // T is deduced to `S` in all cases
return S1{a};
// return struct S1{a}; // NOK
}
int main() {
// foo(struct S1{i}); // NOK
S1 s1;
foo(s1);
struct S1 s2{2};
foo(s2);
foo(1);
// struct S2 s20; // NOK
S2 s21;
}
Can anyone explain to me what this unsymmetry is about?
It looks like struct S
is not allowed where a ctor call as part of an expression is needed. But if a type S
could also be written as struct S
it should also be ok to use struct S{}
as a ctor call.
the assumption is, that using
struct S
orS
as typename in C++ is a matter of taste ;-)
The above assumption is wrong as there are exceptions to it(as also noted in your example) and the reason has more to do with C compatibility than a matter of taste.
The point is that there are rules for when we can/cannot use struct S1
as a replacement for just S1
. And assuming that we can always use struct S1
as a replacement for S1
is wrong.
The operand of the return statement should be an expression but struct S1{a}
is not an expression and hence cannot be used in the return statement:
//-----vvvvvvvvvvvv----> operand is not an expression
return struct S1{a};
An expression involving struct S1
would look something like:
return (struct S1)a;
There are also situation(s) when we need to use struct S1
and using just S1
won't work. A contrived example is given below:
struct S1
{
};
int S1()
{
std::cout<<"function called"<<std::endl;
return 5;
}
int main()
{
//S1 s; // ERROR: This won't work unless we use struct S1
struct S1 s2; //WORKS
}