Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between using "struct S" or "S" as typename

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.

like image 838
wimalopaan Avatar asked Apr 27 '26 12:04

wimalopaan


2 Answers

Writing struct S1 s1; is allowed in C++ for one reason: compatibility with C. C allows you to have at the same time a function called S1, so struct S1 is an explicit disambiguation. C++ also allows this, for backwards compatibility only.

However, in contexts where backwards compatibility is not applicable, C++ does not. C doesn't have constructors, for instance.

There's one other point of confusion in the question:

typedef S1 S2;
struct S2 s2;

S2 is not a struct name but an alias name, and you can't prefix an alias name with struct.

like image 134
MSalters Avatar answered Apr 30 '26 01:04

MSalters


the assumption is, that using struct S or S 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
}
like image 40
Anoop Rana Avatar answered Apr 30 '26 01:04

Anoop Rana



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!