【问题标题】:C++ std::bind accept typename as first argumentC++ std::bind 接受 typename 作为第一个参数
【发布时间】:2013-09-03 22:09:09
【问题描述】:

我遇到了一些奇怪的行为。

这段代码给了我错误:

struct Game {
    void stop() {std::cout << "success\n";}
};

template<class ...Args>
struct holder {
    std::map<std::string, std::function<void(Args...)>> funcMap;

    template <typename T, typename U>
    void connect(T* targObj, const std::string& funcName) {
        std::function<void(Args...)> newFunc = std::bind(U, targObj); 
        //expected primary expression before ',' token on line above
        funcMap[funcName] = newFunc;
    }

    void invoke(const std::string& funcName, class Args...Vals) 
    {funcMap[funcName](Vals...);}
};

int main() {
    holder<> h;
    Game g;
    h.connect<Game, &Game::stop>(g, "close");
    h.invoke();
}

似乎std::bind 不喜欢类型名作为输入。有解决方法吗?手动使用具有相同参数的std::bind 可以正常工作,但它是更多样板代码:

std::function<void(Args...)> newFunc = std::bind(&ae::Game::stop, targObj);

即使没有任何输入,它仍然在编译时出错。为什么我的功能不起作用?

编辑:感谢您的帮助。事实证明,bind 不接受类型名,它接受地址。

【问题讨论】:

  • 显示编译错误,使用auto代替std::function&lt;void(Args...)&gt;
  • 错误出现在有问题的代码行旁边的注释中。我使用的是自动,但我刚刚尝试过。
  • ae::Game::stop 是类型还是变量还是函数?
  • @Astrognome:提示:函数的实例不是类型。
  • 我会用什么来代替 typename?错误来自绑定不接受模板类型名作为参数。

标签: c++ typename stdbind


【解决方案1】:

我猜这个函数是静态的? 如果没有,您有解决方案,它需要一个要调用的对象。

但是 bind 试图在没有对象的情况下使用参数 "close" 调用 g,如果不是静态则无法工作

【讨论】:

  • 我只需要绑定来接受类型名。如果我直接输入这样的类型: std::function newFunc = std::bind(&ae::Game::stop, targObj);那么它工作正常。
  • 是的,因为这个&amp;ae::Game::stop是一个地址,这个typename &amp;ae::Game::stop 没有任何意义。
【解决方案2】:

真的很简单:

template <typename T, typename U>
void connect(T* targObj, const std::string& funcName) {

TU 必须是类型,因为它们是类型模板。这个函数有点尴尬,它强迫一个人写两个模板参数。

h.connect<Game, &Game::stop>(g, "close");

T=Game,而Game 是一个类型,这很好。 U=&amp;Game::stop,这是void (Game::*)() 的变量/实例,所以这就是你失败的原因。我不知道为什么您的编译器会给出愚蠢的错误。解决方法是将函数变量作为参数传递:

template <typename T>
void connect(T* targObj, void(Game::func*)(Args...), const std::string& funcName) 

并将其称为:

h.connect(g, &Game::stop, "close");

如图所示:http://coliru.stacked-crooked.com/a/895584175a1a6a61

【讨论】:

    【解决方案3】:

    对于任何试图做到这一点的人:

    只需使用宏。如果没有自定义绑定实现,这几乎是不可能的。

    #define BINDMF(a,b,c) (std::bind(&a::b, c))
    

    【讨论】:

    • oh, this?。只需将位更改为有意义的代码即可轻松完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多