Here's a good example: I'm trying to overload OpenGL's glutMouseFunc so it may accept the namespace, and class function of my choosing. The one in particular is Init::DisplayInit::mouse, which is static. The question is, is this possible? If so, how is this achieved?
My Implementation
void glutMouseFunc(void (Init::DisplayInit::*mouse)(int, int, int, int)) {
(*mouse);
}
Errors from Implementation
..\OpenGL_03\/displayinit.h:27: error: variable or field 'glutMouseFunc' declared void
..\OpenGL_03\/displayinit.h:27: error: expected primary-expression before 'int'
..\OpenGL_03\/displayinit.h:27: error: expected primary-expression before 'int'
..\OpenGL_03\/displayinit.h:27: error: expected primary-expression before 'int'
..\OpenGL_03\/displayinit.h:27: error: expected primary-expression before 'int'
..\OpenGL_03\/displayinit.h:27: error: void value not ignored as it ought to be
Note, I put the declaration of the function in the same file's header file. I also made sure both the declaration and the definition of the function resided outside of the namespace declaration (which wraps most of both files, each). As shown, one of the first errors reads the function as a variable or field (???).
That's not a reasonable way to define glutMouseFunc. It isn't supposed to call the callback immediately, it's supposed to save a pointer for later (when mouse activity occurs).
Call the GLUT-provided version, and pass the address of your function:
#include <GL/glut.h>
glutMouseFunc(&Init::DisplayInit::mouse);
Static member functions are compatible with ordinary function pointers.
The answer to the headline question is "Yes; functions can accept static function pointers as arguments".
You don't specify the namespace or class in the pointer to function argument specification in the function using it:
void glutMouseFunc(void (*mouse)(int, int, int, int)) {
(*mouse)(1, 2, 3, 4);
}
You do specify the namespace or class in the invocation of the function:
glutMouseFunc(Init::DisplayInit::mouse);
Related
While looking for some help with a problem of mine, I've found this post: error: no matching function for call to 'begin(int*&)' c++
I get it why there's an error there, but why does it say "... for call to 'begin(int*&)'" and not "... for call to 'begin(int*)"? It looks to me like the ia pointer is being passed by value and not reference.
Just for reference (no pun intended) - the following code didn't compile with the message no matching function for call to 'begin(int&)':
#include <iostream>
#include <iterator>
using namespace std;
void print(int ia[])
{
int *p = begin(ia);
while(p != end(ia))
cout<<*p++<<'\t';
}
int main()
{
int ia[] = {1,2,3,4},i;
print(ia);
return 0;
}
Since no matching function could be found, the compiler tells you the specific types of the parameters being passed as that's the only information it has to work with. Since you have a named lvalue here it's first assumption is that you're passing by reference and so that's what the diagnostic message prints.
If for example you had passed a literal there would be no way for a reference function to be correct so it would assume you were passing by value.
For me the code above compiles with the same error:
'no matching function for call to ‘begin(int*&)'
And what is more important:
error: request for member ‘begin’ in ‘__cont’, which is of non-class type ‘int*’
Take a look at the std::begin signature: http://en.cppreference.com/w/cpp/iterator/begin
In your example template ia will be int* as array gets implicitly converted. Next take a look link above and see that all signatures that are not arrays has:
-> decltype(c.begin()).
I need to write a function that isn't part of my class MainWindow (this is a Qt project) so that it can be used in a thread, but I also need it to use a member of MainWindow inside it. Here is the code I have written:
void nameChange(TMAPI *tmapi) {
tmapi->writeString(0x001bbbc2c, qPrintable(n));
}
void MainWindow::on_button_clicked() {
std::thread id(nameChange, this->tmapi);
id.join();
}
I get two errors from this (they are the same error but point to different lines of code in the file <functional>):
error: no type named 'type' in 'class std::result_of<void (*(TMAPI))(TMAPI*)>
Calling nameChange like this seems to work:
TMAPI tmapi;
std::thread id(nameChange, &tmapi);
How can I get the first way to work where I pass in the current object's (this's) instance of tmapi? Thanks.
nameChange takes a TMAPI *. You are trying to pass it a TMAPI. Hence the super cryptic error:
error: no type named 'type' in 'class std::result_of<void (*(TMAPI))(TMAPI*)>
The result_of metafunction is used like result_of<F(Args...)>. In this case, that type indicates that you're trying to call a void(*)(TMAPI*) with a TMAPI - which is not a valid thing to do.
So just pass a pointer like the function expects:
std::thread id(nameChange, &this->tmapi);
I've tried this declaration:
using fp_type = void (*)(fp_type);
Unsurprisingly, it does not work.
a.cpp: In function 'int main()':
a.cpp:13:26: error: expected ';' before '(' token
using fp_type = void(*)(fp_type);
^
a.cpp:13:34: error: expected primary-expression before ')' token
using fp_type = void(*)(fp_type);
Is there a workaround? I was thinking about a reinterpret_cast from a dummy function pointer type, but I am not sure how standard-compliant that is. I am looking into this because I don't want to capture a lambda in a ::std::function, and then use it recursively. I'd like to pass it a function pointer to itself.
5.2.10/6 guarantees you can reinterpret_cast a function pointer to a function pointer of different type, and when you cast it back to the original type, you get back the original pointer value.
I would prefer this:
void foo (struct foo_wrapper&);
struct foo_wrapper {
void (*pf) (struct foo_wrapper&);
// add constructor and accessor for convenience
};
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.
I have a function (assign) in a class (graph) in a header file. The objective of this function is to print a 2d vector:
class Graph
{
public:
void printvec(vector< vector<double> >&PRRMap);
};
I call this function from a cpp file such as:
Graph G;
G.printvec(vector< vector<double> > &PRRmap);
I get the following error:
error: expected primary-expression before ‘&’ token
How can I fix this?
void printvec(vector< vector<double> >&PRRMap);
This is a declaration. It includes formal parameters, each of which specifies a type and an optional name.
G.printvec(a_map);
This is a function call. It includes actual parameters, each of which is an expression, aka value. The type is not named during a function call. But you do need to specify the name of the vector you want printed.
The type of the actual parameter expression is checked against the formal parameter type specified in the function declaration. If they don't match, the compiler will look for a suitable conversion, and if it can't find one, you will get a compile error.
Since your function requires a non-const reference, most conversions will not be allowed here. You should specify the name of a suitable vector-of-vectors object that you have prepared with the data to be printed.
when you call the function you don't need the & operator
only the variable (a valid reference)