如何传递函数指针并在C ++函数中进行比较?

时间:2018-03-29 22:06:03

标签: c++ function pointers function-pointers

出于测试原因,我有一定数量的方法,其在C ++中的签名如下:

dvec3 (*)(dvec3, dvec3, double)

我把它们放在一个载体中,如下所示:

vector<dvec3 (*)(dvec3, dvec3, double)> methods = {lerp, plerp, splerp, ilerp};

这个想法是创建一个函数,它接受函数指针并返回一个字符串来标识当前正在使用的函数(即我想打印出上面4个中正在使用的函数)

为此,我尝试按如下方式编写方法(我故意省略大多数情况):

string inline erpToString(dvec3 (*f)(dvec3, dvec3, double))
{
    if (f==lerp)
    {
        return "Lerp";
    }
}

但是上面没有编译,错误消息表明它是一个转换错误。我做错了什么?

编辑:

编译器消息:

/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

编辑:

我已经制作了具有相同逻辑的最小可能文件,但它不会重现错误:

#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()
{

}

使用代码显示其他方法(ilerp和公司)可以正常工作。所以我似乎有一个名称空间冲突(使用名称空间的yay)。 SInce GLM定义了一个lerp函数,但我需要使用的是我定义的函数。有人有建议吗?

4 个答案:

答案 0 :(得分:3)

您可以使用usingtypedef来简化所有事情。代码对我有用

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";

答案 1 :(得分:0)

问题是由于GLM定义了lerp函数引起的,因此编译器也无法选择我所指的函数。

正如评论中所建议的那样,解决方案是将我的功能从mlerp重命名为select 'BCI.AX' as code, d.dt, pe.price from generate_series(date_trunc('day', NOW() - INTERVAL '1 year'), NOW(), INTERVAL '1 day') d(dt) left join price_events pe on date_trunc('day', pe.date) = d.dt and pe.code = 'BCI.AX';

我想这是一个非常好的例子,为什么使用命名空间不是一个好主意。

答案 2 :(得分:0)

这不是解决错误问题的答案,而是您尝试给出正在使用的方法名称的答案。

我建议你使用std :: unordered_map来区分不同的函数。

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];
}

答案 3 :(得分:-1)

关键是‘<unresolved overloaded function type>’

特别是,您有两个lerp函数。这通常是允许的。在大多数情况下,C ++会找出你想要的那个。例如,当您调用lerp(arg1,arg2, arg3)时,C ++将使用这三个参数执行重载解析。但在f==lerp中,重载解析没有三个参数。这就是C ++说&#34;未解决的重载&#34;。

的原因

解决方案是将lerp转换为f:if (f==static_cast<decltype(f)>(&lerp))的类型。用于重载解析的三个参数是f