brace initialized function pointer array: invalid conversion from 'void (*(*)())()' to 'void (*)()' - c++

In my arduino sketch I need an array of function pointers with the signature void foo().
I'm using the ino command line utillity on linux (which uses avr-g++ under the hood).
However I'm getting a very strange error while defining the array.
error:
error: invalid conversion from ‘void (* (*)())()’ to ‘void (*)()’
in this piece of code
void (*mode_setup[])(void) = {
&show_time_setup,
&set_time_setup,
&set_alarm_setup,
&set_date_setup // <-- generates 3 identical error on this line
};
I don't understand what I'm doing wrong, since... int foo[] = { 1, 2, 3 }; ..is perfectly valid, and void (*foo)(void) is the syntax for function pointer.
what am I missing?
edit: NEVERMIND IM STUPID
the functions were not void foo(), but fptr foo() [fptr=function pointer typedef]
sincere appologies for wasting peoples time

I can reproduce your error message with this code
void (*foo())() {}
void (*arr[])(void) = { &foo };
So it looks like the signature of the function(s) is not what you think it is. An array to hold a pointer to foo would need to be declared like this:
void (*(*arr[])())(void) = {
&foo
};
If I were you, I'd consider typedefs...

Related

Array bound set by a function of a generic

I want to set the array length to be the minimum of a constant and a generic like this:
template <int foo> struct Bar{
void my_func( int const (&my_array)[std::min(5, foo)] ) { /*...*/ }
};
This code compiles with clang++ but not g++ and I need my code to work with both. The error g++ gives is: error: array bound is not an integer constant before ']' token. How I can set the length of this array to be the minimum of foo and 5?
When I use clang++ I run into the problem that I can't get anything to bind to my_array. I want to run something like:
int main() {
static const int var[5] = {0,1,2,3,4};
Bar<5> bar;
bar.my_func(var);
}
But when I try to compile this code in clang++ I get: error: reference to type 'const int [*]' could not bind to an lvalue of type 'const int [5]'.
If I get rid of the std::min() stuff and replace it with foo the code compiles and runs fine.
Notes:
To get this code to compile you'll need to #include <algorithm> or similar to access std::min.
I don't think that this being part of a template should matter but when I try similar things with non-template function such as:
const int const_five = 5;
void new_func( int const (&my_array)[std::min(5,const_five)] ) { /*...*/ }
g++ says: error: variable or field 'new_func' declared void and clang++ says candidate function not viable: no known conversion from 'const int [5]' to 'const int [std::min(5, const_five)]' for 1st argument which both look like similar problems.
For int const (&my_array)[std::min(5, foo)] to compile, you need a version of std::min which is constexpr. It is since C++14.
Check the default value for -std of gcc and clang you use (its version-dependant). Ultimately, compile with -std=c++14.
Provided by StoryTeller, a nice working MCVE.
Keep it simple:
[foo < 5 ? foo : 5]

Pointer static method that points to no static method

I've been trying to make a pointer function that points to a method doing something like this(visual C++):
struct test
{
int tst(int a)
{
return a * 4;
}
};
// ok, this the visual C++ compiler does not accept it... (mingw accept it)
int(*tstptr)(int) = (int(*)(int))&test::tst;
Then I've done something like this:
struct Dx
{
int SomeMethod()
{
return 4;
}
};
struct Dy
{
static int(*pSomeMethod)();
};
int(Dy::*pSomeMethod)() = (int( Dy::*)())&Dx::SomeMethod;
So far so good, this compiles without problems, but if I try call her:
Dy::pSomeMethod();
The compiler returns me:
Error 1 error LNK2001: external symbol "public: static int (__stdcall
* Dy::pSomeMethod) (void)" (? PSomeMethod#Dy##2P6GHXZA) unresolved
which I do not understand, because it is not suppose pSomeMethod he is not pointing at SomeMethod ?
The type of &test::tst is int (test::*) (int), which is a member function pointer.
You are trying to convert it to a regular pointer type, which is not possible because they are completely different.
That's why you will have this type cast error:
error C2440: 'type cast' :
cannot convert from 'int (__thiscall test::* )(int)' to 'int (__cdecl *)(int)'
int(Dy::*pSomeMethod)() = (int( Dy::*)())&Dx::SomeMethod;
Type Checked, so no complain from compiler.
As for:
Dy::pSomeMethod();
This a __cdecl.
But, SomeMethod is a __thiscall, which means it's really like this
int SomeMethod( Dx &this);
So, linker can't find a match.
You simply can't call non-static method without object of class Dx.
Your declaration of pSomeMethod defines a pointer to a function within class Dy that returns an int. You want to declare it as it appears in the linker error:
int (*Dy::pSomeMethod)();
which is a member of Dy that is a pointer to a function returning an int.
What you're trying to do won't work, since Dx::SomeMethod is a member function of Dx, which needs a this pointer. Calling thru pSomeMethod won't have one.
When done right, you can just assign the address of the function to the pointer without using a cast.

Unit testing a vector string

I have this really simple line of code in my production-code(A.cpp) as follows:
std::string A::getString(int i) {
return sVect_[i];
}
with the header as follows:
class A{
public:
std::string getString(int i);
...
private:
vector<std::string> sVect_;
...
};
I've been trying to test the getString() function using googletest but an error keeps popping out:
error: invalid conversion from 'char* (*)(const char*, int)throw ()' to 'int'
error: initializing argument 1 of 'std::string A::getString(i)'
This was my test program:
TEST(ATest, getString){
A a;
EXPECT_EQ("c", a.getString(i));
}
I couldn't quite grasp the workaround of the vector string and how to call it in my test program without ever changing the production code. I even use the hack, adding #define statements, to access the private member but still couldn't do it.
How do my test actually looks like to successfully call that function?
Note: I'm on Linux and using gcc. Thank you in advance guys.
Perhaps the error message is misleading. Have you defined i globally somewhere else? To me it looks like in the local scope because it does not know what the value of the variable i is, it is misbehaving in an unexpected way
TEST(ATest, getString){
A a;
EXPECT_EQ("c", a.getString(i)); //here what is the 'i' and where is it defined
}

error: expected primary-expression before ')' token (C)

I am trying to call a function named characterSelection(SDL_Surface *screen, struct SelectionneNonSelectionne sel) which returns a void
This is the .h of the function I try to call:
struct SelectionneNonSelectionne;
void characterSelection(SDL_Surface *screen, struct SelectionneNonSelectionne);
void resetSelection(SDL_Surface *screen, struct SelectionneNonSelectionne);
On my main function, I try to call it like this:
characterSelection(screen, SelectionneNonSelectionne);
When I compile, I have the message:
error: expected primary-expression before ')' token
I made the includes. I suppose I miscall the second argument, my struct. But, I can't find why on the net.
Have you got any idea about what I did wrong?
You should create a variable of the type SelectionneNonSelectionne.
struct SelectionneNonSelectionne var;
After that pass that variable to the function like
characterSelection(screen, var);
The error is caused since you are passing the type name SelectionneNonSelectionne
A function call needs to be performed with objects. You are doing the equivalent of this:
// function declaration/definition
void foo(int) {}
// function call
foo(int); // wat!??
i.e. passing a type where an object is required. This makes no sense in C or C++. You need to be doing
int i = 42;
foo(i);
or
foo(42);
You're passing a type as an argument, not an object. You need to do characterSelection(screen, test); where test is of type SelectionneNonSelectionne.
I seen this problem with the latest nightly build of Code::Blocks. When I switched back to the stable release of Code::Blocks, 20.03 at the time of this writing, the problem went away and my code compiled and ran without problems. I'm not sure what Code::Blocks is doing, but it is very annoying. I got this repeatedly on a C++ project for every NULL in my code, forcing me to use nullptr instead.

gluTessCallback error C2440

I am trying to use the function gluTessCallback but I get C2440 error. I have no idea why.
Here is the code:
#define callback void(CALLBACK*)()
template<typename T>
class Tessellation
{
private:
GLUtesselator *pTess;
void CALLBACK tessError(GLenum error)
{
sendErrorMessage((char *)gluErrorString(error), true);
}
public:
void Triangulation3D(T* & point, short numOfPoints)
{
pTess = gluNewTess();
gluTessCallback(pTess, GLU_TESS_ERROR, (callback)tessError);
}
};
The error is on gluTessCallback function:
error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'void (__stdcall *)(void)'
Why do I get this compile error?
The error id C2440 on Visual Studio is a type conversion error.
The problem in your code is that you are trying to pass a class method Tessellation::tessError() as function pointer to gluTessCallback(), which expects a pointer to a global C-style function.
A class method is very different from a free/global function and you cannot pass it as a simple function pointer because it needs an object to go along with it every time, the this pointer.
A solution to your problem would be to declare tessError() as a static method, making it effectively the same as a free/global function scoped inside the class, like so:
template<typename T>
class Tessellation
{
private:
static void CALLBACK tessError(GLenum error)
{
sendErrorMessage((char *)gluErrorString(error), true);
}
...
And pass it to gluTessCallback():
gluTessCallback(pTess, GLU_TESS_ERROR, (callback)&Tessellation<T>::tessError);
The only downside to this approach is that a static tessError() can no longer access class variables. Which doesn't seem like a problem to you, since it is not doing so right now, it appears.