首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法理解(并修复)为什么会存在这样的警告:"call of overload xxx is ambiguous“(重载xxx调用不明确)

无法理解(并修复)为什么会存在这样的警告:"call of overload xxx is ambiguous“(重载xxx调用不明确)
EN

Stack Overflow用户
提问于 2019-04-08 02:59:09
回答 1查看 429关注 0票数 0

我纠结于修复这个gcc警告:我得到了方法"registerCalBack“的树版本,它们中的每一个都接受通过std::function引入的不同的"callable”。

我知道重载可以通过编译器考虑参数而不是返回类型来解决,但在这种情况下,我无法理解为什么gcc看到了歧义:对我来说,每个TCallBack...我定义的参数是不同的,当我改变第三个参数的返回类型时,它会编译...这真的让我很困惑。我猜问题的一部分来自于一些参数实际上是不完整的类型,但这就是如何从SDL头文件中访问它们,所以我重现了我在本文中提供的示例。

在代码中的注释中,您可以获得已编译和未编译的定义的示例。

我希望你们中的一些人会比我更了解,现在我不知道去哪里看。在此之前,非常感谢您。

下面是gcc的命令行编译:

代码语言:javascript
复制
-pedantic -W -Wall -Wextra -std=c++2a -Weffc++ -Wfatal-errors -Winit-self -Wnon-virtual-dtor -Winline -Wmissing-declarations -Wunreachable-code -Wshadow -Wswitch-enum -fstack-protector -Wstack-protector -O0

P.

代码语言:javascript
复制
#include <iostream>
#include <functional>

//This is how SDL_Renderer and SDL_Texture are declared in SDL.h, as incomplete type declaration, to make it opaque
//I reproduce it here with other name, to avoid the need to install SDL if you want to test
struct RENDERER;
typedef struct RENDERER RENDERER;

struct TEXTURE;
typedef struct TEXTURE TEXTURE;

//this is stupid, just to make test
struct dumb;
typedef struct dumb dumb;

class ClassUsingCallBacks // an instance of this class will use callbacks
{
public:

    typedef std::function < RENDERER* (void) > TCallBack_GetRenderer;
    typedef std::function < TEXTURE* (const std::string&) > TCallBack_GetTexture;

    //this works: 
    // typedef std::function < dumb* (void) >
    // typedef std::function < dumb* (TEXTURE*) >   
   // typedef std::function < int (TEXTURE*) >  
    // typedef std::function < TEXTURE* (TEXTURE*) > 

    // BUT THIS FAILED TO COMPILE : 
    // typdef std::function < void (TEXTURE*) >
    // typdef std::function < void* (TEXTURE*) >
    // typedef std::function < void (const std::string&, int, int, int) 

    typedef std::function < void (TEXTURE*) > TCallBack_removeTexture;

    virtual ~ClassUsingCallBacks() {};

    void registerCallBack(TCallBack_GetRenderer cb) {
        std::cout << "Register a TCallBack_GetRenderer" << std::endl;
        getRenderer = cb;
    }

    void registerCallBack(TCallBack_GetTexture cb) {
        std::cout << "Register a TCallBack_GetTexture" << std::endl;
        getTexture = cb;
    }

    void registerCallBack(TCallBack_removeTexture cb) {
        std::cout << "Register a TCallBack_removeTexture" << std::endl;
        removeTexture = cb;
    }

    //to test registered callbacks
    void makeCalls(void) {
        if (getRenderer) getRenderer();
        if (getTexture)  getTexture("a name");
        //not this one since it's the one we failed to implement :/
        // if (removeTexture) removeTexture();
    }

protected:

    TCallBack_GetRenderer   getRenderer {};
    TCallBack_GetTexture    getTexture  {};
    TCallBack_removeTexture removeTexture {};
};

class ClassWithCallBacks
{
public:

    virtual ~ClassWithCallBacks() {};

    RENDERER* getRenderer(void) {
        std::cout << "Inside getRenderer" << std::endl;
        return nullptr;
    }

    TEXTURE* getTexture(const std::string& s) {
        (void)s;
        std::cout << "Inside getTexture" << std::endl;
        return nullptr;
    }

    void removeTexture(TEXTURE* t) {
        (void)t;
        std::cout << "Inside removeTexture" << std::endl;
    }
};

int main(int argc, char **argv)
{
    (void)argc;
    (void)argv;

    std::cout << "entering main" << std::endl;

   ClassWithCallBacks   calledObject; 
    ClassUsingCallBacks user;

    auto cb_1 = std::bind(&ClassWithCallBacks::getRenderer, calledObject);
    user.registerCallBack(cb_1);    

    auto cb_2 = std::bind(&ClassWithCallBacks::getTexture, calledObject, std::placeholders::_1);
    user.registerCallBack(cb_2);    

    user.makeCalls();

    std::cout << "Leaving main" << std::endl;

    return 0;
}
EN

回答 1

Stack Overflow用户

发布于 2019-04-08 09:05:02

std::bind生成一个接受任意数量的参数的callable对象,并简单地丢弃那些不需要转发给绑定的callable的参数。

std::function<void(Something)>接受返回结果的callable,然后简单地丢弃该结果。

因此,std::function<RENDERER* (void)>std::function<void (TEXTURE*)>都可以接受cb_1。它可以接受(并忽略) TEXTURE*参数,并且函数可以忽略它的返回值。

基本上,您在很大程度上依赖于类型擦除,但希望您正在擦除的类型仍然有助于指导重载解决。就我个人而言,我会为这三个registerXXX函数指定不同的名称,以反映它们所注册的回调类型。没有过载,没有问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55562577

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档