This question already has answers here:
My attempt at value initialization is interpreted as a function declaration, and why doesn't A a(()); solve it?
(5 answers)
Closed 6 years ago.
First a disclaimer. I've been reading the multitude of questions on this topic, yet I can't get mine to work for me. Mostly I was basing my attempt off of this link, which seems to imply that as long as the function definition has & in it, then I can just pass the object into the function by name. However I keep getting the following errors:
assembler.cpp: In function ‘int main()’:
assembler.cpp:56:21: error: invalid initialization of non-const reference of type ‘Symbol_Table&’ from an rvalue of type ‘Symbol_Table (*)()’
get_input(Table_obj);
assembler.cpp:30:6: error: in passing argument 1 of ‘void get_input(Symbol_Table&)’
void get_input(Symbol_Table& Table_ptr)
As for my actual code, the relevant bits are below. The get_input function is just reading from a file and creating an object of a different type to work with. Through the course of the program running, the Symbol_Table object will have it's members changed so I need to pass it by reference without it being const, which was the only "solution" I could find.
void get_input(Symbol_Table& Table_ptr)
{
do_stuff();
}
int main()
{
Symbol_Table Table_obj();
get_input(Table_obj);
}
I don't think the class definition of Symbol_Table is needed, but I can edit it in if needed.
Symbol_Table Table_obj();
That doesn't create a variable called Table_obj of type Symbol_Table, that's a declaration for a function called Table_obj which takes no arguments and returns a Symbol_Table.
Do one of these:
Symbol_Table Table_obj;
Symbol_Table Table_obj{}; //C++11
You are declaring a function named Table_obj which will return Symbol_Table. This is not what you intend.
int main()
{
Symbol_Table Table_obj; // Construct an object
get_input(Table_obj);
}
This is like:
int get(); // Function
But you want:
int get; // Variable
Confusion reason:
int get(0); // int constructor takes one argument
The problem is that
Symbol_Table Table_obj();
does not make a Symbol_Table object named Table_obj but instead makes a function named Table_obj that takes nothing and returns a Symbol_Table. Change it to
Symbol_Table Table_obj;
and it will compile just fine.
Related
This question already has answers here:
How to create temporary object in C++
(2 answers)
Why does C++ allow us to surround the variable name in parentheses when declaring a variable?
(2 answers)
C++ temporary class instantiation ambiguously
(2 answers)
Closed 3 years ago.
sorry for the question title but I didn't know a correct title for my problem. I have the following code example:
struct test {
test(int a) {
}
};
int main() {
test(1);
return 0;
}
The above example code works. Now i do (in my understanding) the same a bit differently:
struct test {
test(int a) {
}
};
int main() {
int a = 0;
test(a);
return 0;
}
When I compile this I get the following error:
error: redefinition of 'a' with a different type: 'test' vs 'int'
But in my opinion it gets really strange when I try this:
struct test {
test(int a) {
}
};
int main() {
int a = 0;
test((int)a);
return 0;
}
the above example works again and really confuses me since I don't see the difference (except casting an int to an int). Can anyone explain what's going on? Thank you in advance.
You forgot to give your test variable a name, causing test(a); to be a declaration of a variable named a of type test.
In the other cases, since test(1) and test((int)a) cannot be declarations, but must be some kind of call, your compiler will treat that as constructing a temporary object of type test without a name.
This is really tricky:
test(1);
This is a construction of test with argument 1.
int a = 1;
test(a);
The compiler reads this as test a; (instance of test named a – with default construction). That test doesn't even provide a default constructor isn't considered by compiler at this point.
The fix (found by OP):
int a = 1;
test((int)a);
Now, the compiler is explicitly told to read a as expression (but not as identifier).
The syntax of defining variables in C++ is kind of quirky...
When you do
test(1);
you create a temporary object of the test structure. This object will be destructed immediately.
But when you do
test(a);
you don't create a temporary test object, you actually define a variable named a. It's equivalent to
test a;
You can solve this problem by using curly-braces
test{a};
Or by using an explicit expression for the "argument" (like you do with your cast), as such can't be used as variable names. In similar situation where you need to disambiguate between variables and expressions it's common to use the unary + as in
test(+a);
In ISO C++ Standard (ISO/IEC 14882) 2003, at section 3.2:
In any translation unit, a template, type, function, or object can have no more than one definition.
Please note that The One Definition Rule (ODR) is an important concept in the C++ programming language.
If you want to have many functions with same name (and different signatures, of course), function overloading is a feature which you want.
This question already has answers here:
A confusing detail about the Most Vexing Parse
(4 answers)
Closed 3 years ago.
Taken directly from http://herbsutter.com/2013/05/09/gotw-1-solution/
While widget w(); is clear for me, I have no idea how can the below code be a function declaration?
// same problem (gadget and doodad are types)
//
widget w( gadget(), doodad() ); // pitfall: not a variable declaration
How is this possible?
In a function declaration, arguments of type array decay into pointers to the first element, arguments of type function decay into a function pointer, so the signature would be:
widget w( gadget(*)(), doodad(*)() );
That is, a function that takes as the first argument a pointer to a function taking no arguments and returning gadget, that takes as second argument a pointer to a function taking no arguments and returning a doodad and that the function itself returns a widget
There are even more interesting or confusing cases, like:
// assume 'x' is a variable defined somewhere:
widget w(gadget(x));
How could that be interpreted as a function declaration? I mean, x is a variable, right? Well, when declaring a variable you can add extra parenthesis, so gadget x; and gadget (x); both declare the same variable x. The same applies to function arguments so the code above looks like a declaration of a function that takes a first argument named x of type gadget and returns a widget...
It's function that gets two functions, that returns gadget and doodad and either of them gets no arguments.
Example that compiles fine.
#include <iostream>
class widget{};
class gadget{};
class doodad{};
gadget a(){}
doodad b() {};
widget w( gadget(), doodad() ){
}
int main() {
w(a,b);
return 0;
}
http://ideone.com/YjZK9Y
If I have this generic method, where a type Foo object is returned using parameters derived from string s:
Foo createFoo(string s)
{
int index, first, second, third, fourth, fifth;
Foo fooName(int first, int second,int third,int fourth,int fifth);
return fooName;
}
And then in main, I try to do something like this:
Foo newFoo = createFoo(argv[2]);
Why does the compiler give me this error?
file.cc:30:1: error: ‘Foo’ does not name a type file.cc: In function
‘int main(int, char**)’: file.cc:180:38: error: ‘createFoo’ was not
declared in this scope
Coming from Java, doing something like this doesn't usually give me any problems, why would this be a problem in C++? How could I fix this?
Edit 1:
A few suggestions asked where my Foo class definition is located. It was located after the createFoo method so I moved the createFoo method after the Foo class definition segment of code and tried compiling.
Now a new error occurs:
file.cc: In function ‘Foo createFoo(std::string)’: file.cc:153:9:
error: conversion from ‘Foo (*)(int, int, int, int, int)’ to
non-scalar type ‘Foo’ requested
You didn't include the header that defines "Foo", or you forgot to add a using directive to pull it in from the namespace where it is defined.
The statement return fooName; is returning the function fooName, I think you intended to return the result of the function call, it should be something like return fooName(first, second, third, fourth, fifth);
Mert was right in questioning my method location. The method codeblock should have been located after the Foo class definition location within the file.
Concerning your second error, the conversion one:
Foo fooName(int first, int second,int third,int fourth,int fifth);
You intend to create new object instance, passing some parameters to the object constructor. But instead you end up declaring a new function. Remove type names (the "int"s) from parameters to fix this.
You should also be aware of the most vexing parse.
code snippet:
// some code
SDL_Surface* t = Display->render_text(text);
int z=100;
Display->blit_image(t,z,100);
// some more code
does not compile because z magically changes to an int&,
file.cpp:48: error: no matching function for call to ‘display::blit_image(SDL_Surface*&, int&, int)
how can this happen?
post scriptum:
the following works if i put them in place of Display->blit_image(t,z,100)
Display->blit_image(t,z,100,0);
but i am sure that th 4th param is optional because the exact same function works elsewhere without it
pps: i created a minimal-case of my code that behaves as describd above
it's 3 files:
monkeycard.cpp: http://pastebin.com/pqVg2yDi
display.hpp: http://pastebin.com/xPKgWWbW
display.cpp: http://pastebin.com/nEfFX1wj
g++ -c display.cpp monkeycard.cpp fails with:
monkeycard.cpp: In member function ‘void monkeycard::messagebox(std::string)’:
monkeycard.cpp:28: error: no matching function for call to ‘display::blit_image(SDL_Surface*&, int&, int)’
display.hpp:26: note: candidates are: void display::blit_image(SDL_Surface*, int, int, SDL_Rect*)
The error message tells you what you're trying to pass. With automatic conversions and whatnot, that doesn't mean the function must have exactly that signature.
int& here just means that the parameter you've provided is an lvalue, and so it could be passed as a non-const reference. A function can match with that parameter as an int&, const int&, int, long, const float&, etc.
the point is that if instead of z i
write 100 it works.
That's interesting. I can't immediately think of a way to write a function that accepts an integer literal, but not an integer variable. The following code compiles, of course:
struct SDL_Surface;
struct SDL_Rect;
struct display {
void foo(SDL_Surface* img, int x=0, int y=0, SDL_Rect* clip=0) {}
};
int main() {
display d;
int z = 0;
SDL_Surface *p = 0;
d.foo(p,z,100);
}
So there must be something else you haven't mentioned yet, which causes the issue.
Edit: visitor and Charles Bailey (in a comment) have the answer. The defaults are missing from your declaration of the function, so as far as the compiler is concerned you are trying to call a 4-parameter function with 3 arguments. The & is not the problem.
For future reference: when James McNellis asked you for "the" declaration of your function, he meant the declaration which is visible in the translation unit making the call. In your pastebin code, the definition is not visible in that translation unit, and the compiler cannot reach in to a completely different .cpp file and realise that the function is supposed to have parameter defaults. In C++, default values are set up in the calling code, for reasons to do with how calling conventions work.
Having seen the code, the defaults should be given in the header and not in the implementation file.
When you are compiling "monkeycard.cpp", the compiler has only the information in the headers to work with. The compiler has no idea that blit_image has default arguments, and therefore cannot match the function to call.
I suspect that the function isn't declared properly.
There needs to be a prototype inside the class display scope such as:
void blit_image(SDL_Surface* img, int x=0, int y=0, SDL_Rect* clip=NULL);
When you pass an int & parameter (such as any named variable of type int) to an int argument, the value of the int & is copied into the new object of type int. The difference in types implies a conversion which entails a copy which implements pass-by-value. That is just how the C++ formalism works.
The error message you see is nothing else than a specific convention, which that particular compiler uses to generate error messages in cases like that. Apparently, when the compiler is unable to resolve a function call, it generates an error message where every Lvalue argument is reported as having reference type and every Rvalue argument is reported as having non-reference type. This makes some sense, since references in C++ exist specifically for implementing the concept of run-time-bound Lvalue. In fact, it might even turn out that this is exactly how the overload resolution is implemented internally in that compiler.
As for the reason for the error: the function you are trying to call does not exist (or exists, but has a non-matching set of parameters).
P.S. You said in the comments that the matching function actually does exist. That would mean that there's either a problem with the visibility of the function declaration, or a problem with the code you posted being "fake" (i.e. it is not the code you were actually compiling).
Primitives are not reference types in C++.
How do you know that it's the int& that's the cause for the error? The error simply says that the signature is in error. I'd recommend going back and checking the method signature to see what the root cause is.
For example:
struct test
{};
void thing(test())
{}
int main()
{
thing(test());
}
This code would give me error; however, the next example won't give me error:
void thing(int())
{}
int main()
{
thing(int());
}
My main question is, why the first example isn't possible and the second one is? Ultimately, both test and int are types, so I can't think why declaring an anonymous object of test in the thing function argument list isn't possible whereas declaring an anonymous object of type int in the thing function argument list is.
It is possible; it's just that you're doing it wrong.
Here is a declaration of a function taking an unnamed parameter of type test:
void thing(test);
Here is a declaration of a function taking an unnamed parameter of type pointer-to-function-returning-test:
void thing(test());
You want the former, not the latter.
That your second code example works is actually a magical oddity, stemming from the fact that int() is 0 is a valid null pointer constant, which may be used to initialise a function pointer; the example breaks as soon as you swap int() for some other integer, or if you run the code in a completely compliant C++14 compiler (because C++14 made it so that 0 but not int() is a valid null pointer constant).