Emscripten 和从 std::bind 到 std::function 的转换

Posted

技术标签:

【中文标题】Emscripten 和从 std::bind 到 std::function 的转换【英文标题】:Emscripten and conversion from std::bind to std::function 【发布时间】:2015-02-11 21:19:37 【问题描述】:

我正在尝试使用 emscripten 编译我的项目。 在 Visual Studio 2013 中,一切正常。

我将函数存储在这个:

template<typename Return, typename ...Arguments>
using CBFunction = std::function<Return(Arguments...)>;

typedef unsigned int CBID;

template<typename Return, typename ...Arguments>
class CBCollection

    std::map<CBID, CBFunction<Return, Arguments...>> cbs;
public:
    CBID addCB(CBFunction<Return, Arguments...> cb)
    
        CBID id = findFreeID();
        cbs[id] = cb;
        return id;
    

    ...

稍后我可以添加简单的成员函数:

CBCollection<void, MatrixStack, float> BeforeRenderCBs;
...
AnimatedSprite::AnimatedSprite()

    using namespace placeholders;
    BeforeRenderCBs.addCB(bind(&AnimatedSprite::beforeRenderCB, this, _1, _2));

使用 emscripten,结果如下:

<scratch space>:624:1: note: expanded from here
"C:/Development/LexUnitEngine/Engine/include/Buffer.h"
^
C:\Development\LexUnitEngine\Engine\source\AnimatedSprite.cpp:76:24: error: no viable conversion from '__bind<void (AnimatedSprite::*)(MatrixStack &, float), AnimatedSprite *, std::__1::placeholders::__ph<1> &, std::__1::placeholders::__ph<2> &>' to 'CBFunction<void, MatrixStack, float>'
      (aka 'std::__1::function<void (MatrixStack, float)>')
        BeforeRenderCBs.addCB(bind(&AnimatedSprite::beforeRenderCB, this, _1, _2));
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\PROGRA~1\EMSCRI~1\EMSCRI~1\129~1.0\system\include\libcxx\functional:1448:5: note: candidate constructor not viable: no known conversion from '__bind<void (AnimatedSprite::*)(MatrixStack &, float), AnimatedSprite *, std::__1::placeholders::__ph<1> &, std::__1::placeholders::__ph<2> &>' to
      'nullptr_t' for 1st argument
    function(nullptr_t) _NOEXCEPT : __f_(0) 
    ^
C:\PROGRA~1\EMSCRI~1\EMSCRI~1\129~1.0\system\include\libcxx\functional:1449:5: note: candidate constructor not viable: no known conversion from '__bind<void (AnimatedSprite::*)(MatrixStack &, float), AnimatedSprite *, std::__1::placeholders::__ph<1> &, std::__1::placeholders::__ph<2> &>' to
      'const std::__1::function<void (MatrixStack, float)> &' for 1st argument
    function(const function&);
    ^
C:\PROGRA~1\EMSCRI~1\EMSCRI~1\129~1.0\system\include\libcxx\functional:1450:5: note: candidate constructor not viable: no known conversion from '__bind<void (AnimatedSprite::*)(MatrixStack &, float), AnimatedSprite *, std::__1::placeholders::__ph<1> &, std::__1::placeholders::__ph<2> &>' to
      'std::__1::function<void (MatrixStack, float)> &&' for 1st argument
    function(function&&) _NOEXCEPT;
    ^
C:\PROGRA~1\EMSCRI~1\EMSCRI~1\129~1.0\system\include\libcxx\functional:1454:41: note: candidate template ignored: disabled by 'enable_if' [with _Fp = std::__1::__bind<void (AnimatedSprite::*)(MatrixStack &, float), AnimatedSprite *, std::__1::placeholders::__ph<1> &, std::__1::placeholders::__ph<2>
      &>]
                                        __callable<_Fp>::value &&
                                        ^
C:/Development/LexUnitEngine/Engine/include/CallbackCollection.h:49:46: note: passing argument to parameter 'cb' here
        CBID addCB(CBFunction<Return, Arguments...> cb)
                                                    ^

我尝试将 CBFunction 切换到

std::function<Return(Arguments...)

到处都是,但它没有解决问题,我需要其他地方的 CBFunction。

emscripten 版本是 1.29.0,clang 3.4

【问题讨论】:

【参考方案1】:

您的类型不匹配。如果您查看编译错误,AnimatedSprite::beforeRenderCB 的类型为:

void (AnimatedSprite::*)(MatrixStack &, float)

但您正试图将其转换为带有签名的std::function

void(MatrixStack, float)

如果您将集合类型更改为:

CBCollection<void, MatrixStack&, float> BeforeRenderCBs;
//                            ^

它应该可以工作。

【讨论】:

以上是关于Emscripten 和从 std::bind 到 std::function 的转换的主要内容,如果未能解决你的问题,请参考以下文章

为啥我会收到带有 std::bind() 的“本地临时返回地址”警告?

std::bind接口与实现

C++ STL应用与实现22: 函数组合之1:如何使用std::bind (since C++11)

C++11 std::bind函数,std::function函数

std::bind 与 std::function 与 Clang 崩溃

本周小贴士#108:避免std::bind