Not that I would ever write the code like the following in my professional work, the following code is legal and compiles without warnings in c++ and c:
#include <stdlib.h>
typedef struct foo { int foo; } foo;
foo * alloc_foo () {
return (struct foo*) malloc(sizeof(foo));
}
struct foo * alloc_struct_foo () {
return (foo*) malloc(sizeof(struct foo));
}
foo * make_foo1 (int val) {
foo * foo = alloc_struct_foo ();
foo->foo = 0;
return foo;
}
struct foo * make_foo2 (int val) {
struct foo * foo = alloc_foo();
foo->foo = 0;
return foo;
}
What makes this legal and unambiguous in C is section 6.2.3 of the C standard:
6.2.3 Name spaces of identifiers
If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers (label names; tags of structures, unions, and enumerations; members of structures or unions; and ordinary identifiers).
Note that thanks to label names living in their own name spaces, I could have made the code even more obfuscated by using a label foo somewhere.
Add the following and the code does not compile:
int foo (foo * ptr) {
return ++ptr->foo;
}
So, two questions, one related to C and C++ and the other, C++.
C/C++ question: Why can't I define the function foo?
It seems I should be able to define the function foo; function names and variable names are "ordinary identifiers". But if I add that last little bit of code I get error: redefinition of 'foo' as different kind of symbol.
Question: foo * foo; is perfectly legal, so why isn't int foo (foo*); legal?
C++ question: How does this work at all in C++?
The meaning of "name space" takes on a rather different meaning on in C++ than in C. I can't find anything in the C++ standard that talks about the C concept of name spaces, which is what makes the above legal in C.
Question: What makes this legal in C++ (chapter and verse preferred)?
foo * foo; is perfectly legal, so why isn't int foo (foo*); legal?
Because there already is a type named foo in the same declaration context as your function. You cannot have a type and a function of the same name in the same scope.
How does this work at all in C++?
Because you are allowed to hide names in nested scopes. When you declare foo * foo, the first foo refers to the type. The second foo declares a variable -- at that point, the type foo is hidden. Try declaring foo * baz after foo * foo, it should fail.
struct foo {};
void test() {
foo * foo; // first `foo` is the type, second `foo` is the variable
foo * baz; // first `foo` is the variable
}
In C++11 3.3.1/4 says that in a declarative region all declarations of a name must refer to the same entity (or an overload set). There's an exception that allows you to use a class name for a set of function names (so foo() hides class foo) but this doesn't apply if you have a typedef (which you do).
Try it with the typedef struct foo foo omitted in C++.
This doesn't work in C++ either ... the problem is that the pre-processor for gcc/g++ is looking for __cplusplus, not cplusplus. Therefore you pre-processor statements
#if defined FOO && ! defined cplusplus
#undef FOO
#endif
do not work correctly.
Because there is already function foo() it's a default constructof for struct foo
typedef struct foo
{
int a;
foo(int val)
:a(val)
{}
} foo;
int foo(int value)
{
cout << value <<endl;
}
void main()
{
foo foovar = foo(50); // constructor foo or function foo?
}
There are no such things as constructors in C.
Edit specially for Alan Stokes:
typedef struct foo
{
int a;
foo(int val, double val2)
:a(val)
{
cout << val2 << endl;
}
} foo;
int foo(int value, double val2)
{
cout << value << val2 << endl;
}
void main()
{
some_random_func(foo(50, 1.0)); // constructor foo or function foo?
}
Related
It seems you can return an unnamed struct this way:
auto foo() {
struct {
int bar;
int square() {
return bar * bar;
}
} a { 7 };
return a;
}
Is there anyway to do this without the redundant variable name a, thus anonymously?
For starters C++ does not define anonymous structures. I think you mean an unnamed structure.
According ro the C++ Standard the return statement is defined like (8.6 Jump statements)
return expr-or-braced-init-listopt ;
So you may not use a declaration in the return statement. If so then you need prelimary to declare an object of the structure type that will be returned.
I have no idea what the point of this exercise is, so here is an answer that technically does what you ask for:
auto helper()
{
struct {
int x;
} a {0};
return a;
}
decltype(helper()) foo()
{
return {8};
}
https://godbolt.org/z/zA8C1V
The struct is unnamed.
foo does not return a named variable.
Of course this is straight up ridiculous - one would just name the struct instead of this decltype tomfoolery.
No, this is not possible.
The closest you can get is to use a functional-style cast to create a temporary, and use a C99-style scoped-initialiser; GCC allows this in C++ mode, as an extension:
#include <iostream>
#include <string>
auto foo() {
return (struct {
int bar;
int square() {
return bar * bar;
}
}) { 7 };
}
… but this is not portable (and will warn).
Without the braces around 7 the extension is not triggered, and you're back to standard code, in which it is illegal to define a type in a cast.
Instead of writing obtuse code, give your type a name and give your object a name. Your readers will thank you.
None of
struct {/*...*/} foo() { // Illegal
return {/*...*/};
}
auto foo() {
return struct { /*...*/ } { /*...*/ }; // Illegal
}
template <typename T = struct { /*...*/ }> // Illegal
T foo() {
return { /*...*/ };
}
are legal.
You have to, at least, have a named type, or a named instance.
Lambda allows to have neither, but you can only capture and define its operator():
auto foo() {
return [/*...*/](/*...*/) { /*...*/ }; // Legal
}
Returning anonymous struct
There is no such thing as anonymous struct in C++. That's enough to make it impossible.
There is a - limited - way of returning an object of anonymous type from a function: Returning a lambda.
auto make_square_function() {
return [bar = 7]() {
return bar * bar;
};
}
Lambdas are much more limited than general classes though. The members (captures) are encapsulated and cannot be named from the outside of the lambda and there are no member functions other than the function call overload.
Is there anyway to do this without the redundant variable name a
Only if you give the class a name:
struct Squarer {
int bar;
int square() {
return bar * bar;
}
};
auto foo() {
return Squarer{7};
}
Returning an instance of unnamed class is only possible by defining a variable.
Just for fun, another define-the-variable-in-another-function solution (taking inspiration from Max Langhof's answer)
auto foo ()
{
return []{ struct{int bar;} a {7}; return a; }();
}
No, because you need to return an instance of an object, in this case a.
The returned object has to exist somewhere in memory, you can't just return a class definition.
In your example, you don't return an anonymous struct, but you return an instance of that struct.
This question already has an answer here:
Most vexing parse
(1 answer)
Closed 9 years ago.
I have these two classes:
class Foo
{
public:
Foo() { std::cout << "in Foo constructor" << std::endl; }
};
class Bar
{
public:
Bar() {};
Bar(Foo foo);
private:
Foo m_foo;
};
Bar::Bar(Foo foo) :
m_foo(foo)
{
std::cout << "in Bar constructor with argument Foo" << std::endl;
}
int main() {
Bar bar(Foo()); // is something wrong here ?
return 0;
}
I compiled and excuted it , nothing printed on screen, what did Bar bar(Foo()) do ?
I have seen similarity in Do the parentheses after the type name make a difference with new? and Foo f = Foo(); // no matching function for call to 'Foo::Foo(Foo)', but I still can't figure out.
To achieve the same without changing the semantics (ie. not using the copy or assignment constructor), add parentheses to disambiguate the syntax (the compiler does not know if you declare a function locally or if you build an object, by default the former is prioritized by the C++ standard):
int main() {
Bar bar ( (Foo()) );
return 0;
}
As pointed out in the Wikipedia page that was posted in the comments, it is an issue with the C++ grammar itself, not much you can do about it.
OK it has been pointed out that compiler thinks that you are declaring a function. By Pubby and Nbr44. This is a way how to get around it. Just let the compiler know that you are declaring variable.
int main() {
Bar bar = Foo();
return 0;
}
Recently I've been facing a really strange way to write a protoype :
void myProto( QList<::myObject::myStruct> myStructList );
And I'd like to know what does "<::" and ">" mean ?
Thanks !
QList is a template, and QList<Type> is a specialization of that template, with the actual type ::myObject::myStruct.
The :: is the scope resolution operator, which tells the compiler to look for myStruct in the scope of myObject, which itself is at global scope.
::myObject::myStruct
means refer to myStruct defined in class (or namespace) myObject which is located at global scope.
<>
A type goes inside these brackets and it indicates the specialization of the template for that type.
Compile the following program
struct A // GLOBAL A
{
void f()
{ }
};
namespace nm
{
struct A // nm::A
{ };
template <class T>
struct B
{
T a;
};
void f1(B<A> b) // WILL NOT COMPILE
{
b.a.f();
}
void f2(B< ::A> b) // WILL COMPILE
{
b.a.f();
}
}
int main()
{
}
nm::f1 will not compile
nm::f2 will compile
This is because ::A (the global A) has a f member
and
nm::A doesn't have a f member.
struct Foo {};
struct Bar : Foo {};
Foo &foo = Bar; // without ()
I wonder, Is it a legal notation? And if it is legal, could you give some details? Something like, Why it's legal? Or, What is the origin of such a notation?
EDIT: I cannot compile this code. But I met a code like that and wanted to know whether such a notation is allowed (probably just my compiler doesn't support this notation). I'm having some uncertainty since the following notation is quite legal: Foo *pFoo = new Bar;
It should be a compiler error.
g++: error: expected primary-expression before ';' token
Bar is a name of class and it cannot be assigned to reference / variable. Even with putting () it will not compile, unless you make foo a const Foo&.
You cannot assign an class Name to a reference/object. It is neither syntactically valid nor does it make any sense.
You cannot bind a reference to a temporary(rvalue), So following is illegal too:
Foo &foo = Bar();
You can bind a temporary(rvalue) to an const reference, So following is legal:
const Foo &foo = Bar();
The C++ standard specifically allows the 3.
The code as presented is not legal because Bar is the name of a class, not a variable.
The following, however, is:
struct Foo {}
struct Bar : Foo {}
Bar fooBar;
Foo &foo = fooBar; // without ()
It is legal because Bar is a Foo, so you're just giving a different name to your variable fooBar.
Note however that foo, although an alias for fooBar, will interpret the location as a Foo object.
This means the following:
struct Foo { int x; }; //note semicolons after struct declaration
struct Bar : Foo { int y; };
Bar fooBar;
fooBar.y = 2;
fooBar.x = 3;
Foo &foo = fooBar;
int aux;
aux = foo.x; // aux == 3
aux = foo.y; // compile error
You can't assign a value to a reference. So as already mentioned this is not legal regardless of the parentheses.
After getting an answer to this question I discovered there are two valid ways to typedef a function pointer.
typedef void (Function) ();
typedef void (*PFunction) ();
void foo () {}
Function * p = foo;
PFunction q = foo;
I now prefer Function * p to PFunction q but apparently this doesn't work for pointer-to-member functions. Consider this contrived example.
#include <iostream>
struct Base {
typedef void (Base :: *Callback) ();
//^^^ remove this '*' and put it below (i.e. *cb)
Callback cb;
void go () {
(this->*cb) ();
}
virtual void x () = 0;
Base () {
cb = &Base::x;
}
};
struct D1 : public Base {
void x () {
std :: cout << "D1\n";
}
};
struct D2 : public Base {
void x () {
std :: cout << "D2\n";
}
};
int main () {
D1 d1;
D2 d2;
d1 .go ();
d2 .go ();
}
But if I change it to the new preferred style: typedef void (Base :: Callback) () and Callback * cb, I get a compiler error at the point of typedef
extra qualification 'Base::' on member 'Callback'
Demo for error.
Why is this not allowed? Is it simply an oversight or would it cause problems?
For non-member functions, a type such as typedef void(Function)() has several uses, but for member functions the only application is to declare a variable which holds a function pointer. Hence, other than a stylistic preference, there's no strict need to allow this syntax and it has been omitted from the standard.
Background
The :: is a scope resolution operator, and the syntax X::Y is reserved for static member access if X is a class type. So X::*Z was another syntax invented to define pointer-to-member.
Forget member-function for a while, just think about member-data, and see this code:
struct X
{
int a;
};
int X::*pa = &X::a; //pointer-to-member
X x = {100}; //a = 100
cout << (x.*pa) << endl;
It defines a pointer-to-member-data, and the cout uses it to print the value of a of object x, and it prints:
100
Demo : http://www.ideone.com/De2H1
Now think, if X::pa (as opposed to X::*pa) were allowed to do that, then you've written the above as:
int X::pa = X::a; //not &X::a
Seeing this syntax, how would you tell if X::a is a static member or non-static member? That is one reason why the Standard came up with pointer-to-member syntax, and uniformly applies it to non-static member-data as well as non-static member-function.
In fact, you cannot write X::a, you've to write &X::a. The syntax X::a would result in compilation error (see this).
Now extend this argument of member-data to member-function. Suppose you've a typedef defined as:
typedef void fun();
then what do you think the following code does?
struct X
{
fun a;
};
Well, it defines member a of type fun (which is function taking no argument, and returning void), and is equivalent to this:
struct X
{
void a();
};
Surprised? Read on.
struct X
{
fun a; //equivalent to this: void a();
};
void X::a() //yes, you can do this!
{
cout << "haha" << endl;
}
We can use exactly the same syntax to refer to a which is now a member-function:
X x;
x.a(); //normal function call
void (X::*pa)() = &X::a; //pointer-to-member
(x.*pa)(); //using pointer-to-member
The similarity is the synatax on the right hand side : &X::a. Whether a refers to a member-function or member-data, the syntax is same.
Demo : http://www.ideone.com/Y80Mf
Conclusion:
As we know that we cannot write X::a on the RHS, no matter if a is a member-data or member-function. The only syntax which is allowed is &X::f which makes it necessary that the target type (on LHS) must be pointer as well, which in turn makes the syntax void (X::*pa)() absolutely necessary and fundamental, as it fits in with other syntax in the language.
To be precise the two typedef's in the case of the non-member pointers are not the same:
typedef void function();
typedef void (*fptr)();
The first defines function as a function taking no arguments and returning void, while the second defines ftpr as a pointer to function taking no arguments and returning void. The confusion probably arises as the function type will be implicitly converted to a pointer type in many contexts. But not all:
function f; // declares void f();
struct test {
function f; // declares void test::f()
};
void g( function f ); // declares g( void (*f)() ): function decays to pointer to function in declaration
g( f ); // calls g( &f ): function decays to pointer to function
void f() {} // definition of f
// function h = f; // error: cannot assign functions
function *h = f; // f decays to &f
Let's skip the "function" part for a second. In C++, we have the int, the int* and the int Foo::* types. That's a regular integer, pointer to integer, and a pointer to an integer member. There is no fourth type "integer member".
Exactly the same applies to functions: there's just no type "member function", even though there are function types, function pointer types, and member function pointer types.