Does this line declare a function? C++ - c++

I was reading litb's question about SFINAE here and I was wondering exactly what his code is declaring. A simpler (without the templates) example is below:
int (&a())[2];
What exactly is that declaring? What is the role of the &? To add to my confusion, if I declare the following instead
int b()[2];
I get an error about declaring a function that returns an array, while the first line has no such error (therefore, one would think the first declaration is not a function). However, if I try to assign a
a = a;
I get an error saying I'm attempting to assign the function a... so now it is a function. What exactly is this thing?

There's these awesome programs called cdecl and c++decl. They're very helpful for figuring out complicated declarations, especially for the byzantine forms that C and C++ use for function pointers.
tyler#kusari ~ $ c++decl
Type `help' or `?' for help
c++decl> explain int (&a())[2]
declare a as function returning reference to array 2 of int
c++decl> explain int b()[2]
declare b as function returning array 2 of int
a returns a reference, b does not.

For future reference, you may find this link helpful when you have a particularly difficult C/C++ declaration to decipher:
How To Read C Declarations
For completeness, I will repeat what others have said to directly answer your question.
int (&a())[2];
...declares a to be a zero-argument function which returns a reference to an integer array of size 2. (Read the basic rules on the link above to have a clear understanding of how I came up with that.)
int b()[2];
...declares b to be a zero-argument function which returns an integer array of size two.
Hope this helps.

int (&a())[2];
It declares a symbol a that is a function that takes no arguments and returns a reference to a two-element array of integers.
int b()[2];
This declares a symbol b that is a function that takes no arguments and returns a two-element array of integers... this is impossible by the design of the language.
It is relatively simple: get an operator precedence chart, start the symbol name (a) and start applying the operators as you see from their precedence. Write down after each operation applied.

Related

What does void*(*void)(void*) stands for?

And what's the difference between
void*(*void)(void*)
and
void*(*voi)(void*)
and when to use it?
well void*(void)(void) doesn't compile, because it tries to declare a function that returns a void* named void and you can't use keywords of the language as names.
you can't declare an int named void either (int void=5; doesn't work of course).
Now voi is a valid identifier and you can name a function voi.
Trying to get at what you're actually asking the difference between.
void(*name)(void); and void(name)(void); is that one declares a function and the other declares a function pointer.
In fact the brackets on the second example don't do anything. void(name)(void); is the same as void name(void);.
However when declaring function pointers the brackets are needed or the * will bind left to the return type.
Anyway, I'm not sure what exactly you're asking, so you're best off searching the site for other questions regarding function pointers. Like this one that also explains why using void(name)(void) can be different from void(name)().

Strange error with simple struct [duplicate]

First:
int k[] ={1,2,3,4,5};
Second:
struct slk
{
int k[] ={1,2,3,4,5};
};
for those two statements, why does the first one pass the compilation but the second one give me
error:too many initializers for 'int [0]'. the compilation would passed if I set k[5];
What does this error message means? Note: code tested on GNU GCC version 4.7.2
In C++11, in-class member initializers are allowed, but basically act the same as initializing in a member initialization list. Therefore, the size of the array must be explicitly stated.
Stroustrup has a short explanation on his website here.
The error message means that you are providing too many items for an array of length 0, which is what int [] evaluates to in that context.
In the first example, something (actual memory allocation) is actually happening. The computer easily counts the number of items given to it and uses this as the capacity. In the second use, as part of a struct, the array is simply part of the template of a struct. In the second case, a size must explicitly be given and known at compile-time. There is no automatic counting here. It's in a similar vein to function declarations versus definitions as well as variable declarations (tells type but memory is untouched) and their invocation/use (where the program acts).
Probably cause in a struct the compiler needs you to specify the size explicitly.
C initialize array within structure (pun intended)
These are two completely different contexts:
The first is a variable declaration (with an initialiser clause).
The second is a type definition.

Binary compatibility when changing parameter name in C++

I have a question about changing parameter name of a member function.
I have function foo(type iA) then I change to foo(type iB), I think it is bin comp, but I am not sure.
Could you help me to explain the reason? Thanks a lot!
Of course it will be binary compatible because you do not change the type of object. Hence the size stays the same. Name of variable is only for human.
You can actually declare function not giving any names, like:
int funct(void*, int, Object)
When you define it you can use whatever you like
int funct(void* ptr, int something , Object object){return 42;};
It is fine. It also works for class members.
The (I would say main) reason for binary compatibility or incompatibility are the sizes of passed objects. So when you operate on actual binary data, on assembler level no offsets change. If you changed types, arguments would lie in different places in memory, and offsets for them would need to be recalculated. What is important are addresses not aliases or names.
Edits:
For the sake of the completeness.
As #Lightness pointed out, you can also skip names in definition, so the very example I gave could look: int funct(void*, int, Object){return 42;};.
Also regarding #James' comment. I would say that when two objects have the same size, it gets murky. Of course it makes no sense to make such wild conversion from one type to another. However, considering previous example, if you do not use operand it would probably work ... on the assembler level. If sizes differed it would corrupt stack.
However, when I thought how to comment on this problem, I told myself that you ask about c++. So let's look at it from this point of view. I would say that functions are binary compatible when their signature does not change. And names of operands are not part of it in any definition. Function signature is a basis for name mangling and overloading, and the symbol name in the final binary object.
The names of the arguments is just for you to distinguish the arguments. You can have different names in a function declaration and the functions definition.
So this is okay:
void foo(int bar); // Declare function
...
// Define function
void foo(int bibibibibi)
{
...
}
The declaration and definition above is for the same function. C++ does not override or overload functions based on argument names, only argument types.
The compiler does not store the names of arguments (or other variable) except as debug info. The actual generated code have no information about the variable names.

C++ void function declarations [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ Why put void in params?
What's the difference between these two declarations and which is used more commonly?
void function1();
and
void function2( void );
There is no difference in C++, where it is well defined that it represents 0 parameters.
However it does make one in C. A function with (void) means with no parameter, whereas () means with any number of parameters.
From http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fparam_decl.htm
An empty argument list in a function definition indicates that a function
that takes no arguments. An empty argument list in a function declaration
indicates that a function may take any number or type of arguments. Thus,
int f()
{
...
}
indicates that function f takes no arguments. However,
int f();
simply indicates that the number and type of parameters is not known.
To explicitly indicate that a function does not take any arguments, you should
define the function with the keyword void.
There is no difference in C++.
The second declaration just explicitly says that function takes no parameter.
Second is more commonly used in C, First is the one that is more common in C++.
There is a difference in case of C because:
With (void), you're specifying that the function has no parameters, while with () you are specifying that the parameters are unspecified(unknown number of arguments).
However, if it was not a function declaration but a function definition, then even in C it is same as (void).
There is no difference. I'd say the first one is more common, clear and concise.
In C++, there is no difference, and the second form is only retained for C compatibility. The first form is preferred in C++.
In C, they mean different things.
The first form specifies a function which takes an unknown number of arguments, and the second is a function taking zero arguments.
Some very old (non-standard) C compiler might complain about the first one, so the second one should be more portable.
Apart from that, there is no difference.
The first one is used more commonly in user code, quite simply because it's shorter.
actually there is no difference .if you have not any parameters to pass to the method user void or empty parentheses .notice that it just fro passed parameters.if your method has not any returned value you have to use void keyword.the first one is more common in C#

(Obj) C++: Instantiate (reference to) class from template, access its members?

I'm trying to fix something in some Objective C++ (?!) code. I don't know either of those languages, or any of the relevant APIs or the codebase, so I'm getting stymied left and right.
Say I have:
Vector<char, sizeof 'a'>& sourceData();
sourceData->append('f');
When i try to compile that, I get:
error: request for member 'append' in 'WebCore::sourceData', which is of non-class type 'WTF::Vector<char, 1ul >& ()();
In this case, Vector is WTF::Vector (from WebKit or KDE or something), not STD::Vector. append() very much is supposed to be a member of class generated from this template, as seen in this documentation. It's a Vector. It takes the type the template is templated on.
Now, because I never write programs in Real Man's programming languages, I'm hella confused about the notations for references and pointers and dereferences and where we need them.
I ultimately want a Vector reference, because I want to pass it to another function with the signature:
void foobar(const Vector<char>& in, Vector<char>& out)
I'm guessing the const in the foobar() sig is something I can ignore, meaning 'dont worry, this won't be mangled if you pass it in here'.
I've also tried using .append rather than -> because isn't one of the things of C++ references that you can treat them more like they aren't pointers? Either way, its the same error.
I can't quite follow the error message: it makes it sound like sourceData is of type WTF:Vector<char, 1ul>&, which is what I want. It also looks from the those docs of WTF::Vector that when you make a Vector of something, you get an .append(). But I'm not familiar with templates, either, so I can't really tell i I'm reading that right.
EDIT:
(This is a long followup to Pavel Minaev)
WOW THANKS PROBLEM SOLVED!
I was actually just writing an edit to this post that I semi-figured out your first point after coming across a reference on the web that that line tells the compiler your forward declaring a func called sourceData() that takes no params and returns a Vector of chars. so a "non-class type" in this case means a type that is not an instance of a class. I interpreted that as meaning that the type was not a 'klass', i.e. the type of thing you would expect you could call like .addMethod(functionPointer).
Thanks though! Doing what you suggest makes this work I think. Somehow, I'd gotten it into my head (idk from where) that because the func sig was vector&, I needed to declare those as &'s. Like a stack vs. heap pass issue.
Anyway, that was my REAL problem, because I tried what you'd suggested about but that doesn't initialize the reference. You need to explicitly call the constructor, but then when I put anything in the constructor's args to disambiguate from being a forward decl, it failed with some other error about 'temporary's.
So in a sense, I still don't understand what is going on here fully, but I thank you heartily for fixing my problem. if anyone wants to supply some additional elucidation for the benefit of me and future google people, that would be great.
This:
Vector<char, sizeof 'a'>& sourceData();
has declared a global function which takes no arguments and returns a reference to Vector. The name sourceData is therefore of function type. When you try to access a member of that, it rightfully complains that it's not a class/struct/union, and operator-> is simply inapplicable.
To create an object instead, you should omit the parentheses (they are only required when you have any arguments to pass to the constructor, and must be omitted if there are none):
Vector<char, sizeof 'a'> sourceData;
Then you can call append:
sourceData.append('f');
Note that dot is used rather than -> because you have an object, not a pointer to object.
You do not need to do anything special to pass sourceData to a function that wants a Vector&. Just pass the variable - it will be passed by reference automatically:
foobar(sourceData, targetData);
Dipping your toes in C++ is never much fun. In this case, you've run into a couple of classic mistakes. First, you want to create an instance of Vector on the stack. In this case the empty () is interpreted instead as a declaratiton of a function called sourceData that takes no agruments and returns a reference to a Vector. The compiler is complaining that the resulting function is not a class (it's not). To create an instance of Vector instead, declare the instance without the () and remove the &. The parentheses are only required if you are passing arguments to the instance constructor and must be omitted if there are no arguments.
You want
Vector<char, sizeof 'a'> sourceData;
sourceData.append('f');
Vector<char, sizeof 'a'> outData; //if outData is not instantiated already
foobar(sourceData, outData);
This Wikipedia article gives a decent introduction to C++ references.