Reputation: 9536
For testing reasons I have a certain number of methods whose signature in C++ would look like:
dvec3 (*)(dvec3, dvec3, double)
I put them in a vector as follows:
vector<dvec3 (*)(dvec3, dvec3, double)> methods = {lerp, plerp, splerp, ilerp};
The idea is to make a function that takes the function pointer and returns a string to identify the function that is currently being used (i.e I want to print out which function, among the 4 above, is being used)
For this I attempted to write the method as follows (I ommitted most cases on purpose):
string inline erpToString(dvec3 (*f)(dvec3, dvec3, double))
{
if (f==lerp)
{
return "Lerp";
}
}
The above however does not compile, the error message states that it's a casting error. What did I do wrong?
EDIT:
Compiler message:
/home/kronos/Desktop/OpenGL-Template/source/Rendering/rendering.cpp: In function ‘std::__cxx11::string erpToString(glm::dvec3* (*)(glm::dvec3, glm::dvec3, double))’:
/home/kronos/Desktop/OpenGL-Template/source/Rendering/rendering.cpp:1362:7: error: invalid operands of types ‘glm::dvec3* (*)(glm::dvec3, glm::dvec3, double) {aka glm::tvec3<double, (glm::precision)0>* (*)(glm::tvec3<double, (glm::precision)0>, glm::tvec3<double, (glm::precision)0>, double)}’ and ‘<unresolved overloaded function type>’ to binary ‘operator==’
if (f==lerp)
~^~~~~~
make[2]: *** [CMakeFiles/voxel-world.dir/build.make:111: CMakeFiles/voxel-world.dir/source/Rendering/rendering.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:68: CMakeFiles/voxel-world.dir/all] Error 2
EDIT:
I have made the minimum possible file that would have the same logic, however it does not reproduce the error:
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <string>
using namespace std;
using namespace glm;
dvec3 lerp(dvec3 p1, dvec3 p2, double t)
{
return (1-t)*p1+t*p2;
}
string inline erpToString(dvec3 (*f)(dvec3, dvec3, double))
{
if (f==lerp)
{
return "Lerp";
}
}
int main()
{
}
Playing around with the code shows the other methods (ilerp and company) do work. So it seems I have a namespace conflict (yay for using namespaces). SInce GLM defines a lerp function, but the one I need to use is the one I defined. Anyone got a suggestion?
Upvotes: 1
Views: 175
Reputation: 2748
This is not an answer to how to fix the bug, but an answer to your attemp of giving a name of the method your are using.
I suggest you to use std::unordered_map to discriminate different functions.
std::unordered_map<void*, const char*> funcmap{4};
union cast_fptr {
dvec3 (*)(dvec3, dvec3, double) fptr;
void *void_ptr;
};
#define MAP_VAL(FUNC_NAME) std::pair<void*, const char*>{cast_fptr{.fptr = &FUNC_NAME}.void_ptr, #FUNC_NAME}
funcmap.insert({MAP_VAL(lerp), MAP_VAL(plerp), MAP_VAL(splerp), MAP_VAL(ilerp)});
#undef MAP_VAL
inline const char* erpToString(dvec3 (*f)(dvec3, dvec3, double)) noexcept {
return funcmap[f];
}
Upvotes: 0
Reputation: 9536
The problem was caused because GLM defines a lerp Function as well, thus the compiler couldn't choose which function I was referring too.
The solution was, as suggested in the comments, renaming my function from lerp
to mlerp
I guess this is a very good example as to why using namespaces is not a great idea.
Upvotes: 0
Reputation: 179819
The key is ‘<unresolved overloaded function type>’
In particular, you have two lerp
functions. That's generally allowed. In most contexts, C++ will figure out which one you want. For instance, when you call lerp(arg1,arg2, arg3)
, C++ will do overload resolution with those three arguments. But in f==lerp
, there are no three arguments for overload resolution. That is why C++ says "unresolved overload".
The solution is to cast lerp
to the type of f: if (f==static_cast<decltype(f)>(&lerp))
. The three arguments to use for overload resolution are those of f
.
Upvotes: 0
Reputation: 20080
You could use using
or typedef
to simplify all thing. Code works for me
int a(float x, float y, double z)
{
return int(x + y + z);
}
int b(float x, float y, double z)
{
return int(x - y - z);
}
using fdef = int(*)(float, float, double); // or typedef int (*fdef)(float, float, double);
std::vector<fdef> v{a, b};
if (v[0] == a)
std::cout << "qqq\n";
Upvotes: 3