C++ 通用回调实现

标签 c++ c++11 templates flash boost

我有一段代码,它以 XML 的形式从 Flash Player 获取消息,将它们解析为函数和参数,并调用该函数的已注册回调。 我想要替换的代码片段是做得很好(几乎)的通用回调机制: code for the generic callback implementation of flashSDK (ASInterface.inl) .

问题是这段代码是为闪存编写的,我想更换闪存并使用具有相同接口(interface)的其他服务。此回调机制是否有任何标准实现(std?boost?其他开源的东西?)?

此代码实现了通用回调机制,您可以在映射中使用参数数量和类型注册函数:

void SomethingHappened(int a, int b) {print a + b;}
void SomethingElseHappened(string abcd) {print abcd;}
callbacks["SomethingHappened"] = &SomethingHappened;
callbacks["SomethingElseHappened"] = &SomethingElseHappened;

然后搜索它并使用参数数组调用:

Callbacks::iterator itCallback = callbacks.find(functionName);
if (itCallback != callbacks.end())
{
    HRESULT result = itCallback->second.Call(arguments, returnValue);
}

完整使用示例:

//init callbacks
std::map<std::wstring, Callback> callbacks;
void SomethingHappened(int a, int b) {print a + b;}
void SomethingElseHappened(string abcd) {print abcd;}
callbacks[functionName] = &SomethingHappened;

void MessageArrived(string xmlInput)
{
    string functionName = parseFunctionName(xmlInput);
    Callbacks::iterator itCallback = callbacks.find(functionName);
    if (itCallback != callbacks.end())
    {
        //parse arguments
        std::vector<std::wstring> args;
        _Args::split(xml, args);
        ASValue::Array arguments;
        for (size_t i = 0, s = args.size(); i < s; ++i)
        {
            ASValue arg; arg.FromXML(args[i]);
            arguments.push_back(arg);
        }
        ASValue returnValue;
        //***this is where the magic happens: call the function***
        HRESULT result = itCallback->second.Call(arguments, returnValue);
        return result;
    }
}

最佳答案

您可能需要一个 std::function 的包装器,例如:

template <typename T> struct Tag{};

// Convert ASValue to expected type,
// Possibly throw for invalid arguments.
bool Convert(Tag<Bool>, AsValue val) { return (Boolean)val; }
int Convert(Tag<int>, AsValue val) { return (Number)val; }
// ...

struct Callback
{
private:
    template <std::size_t ... Is, typename Ret, typename ... Ts>
    static Ret call_impl(Ret(* func)(Ts...), std::index_sequence<Is...>)
    {
        if (arr.size() != sizeof...(Is)) throw std::invalid_argument{};
        return func(Convert(tag<Ts>{}, arr[Is])...);
    }
public:
    template <typename Ret, typename ... Ts>
    Callback(Ret(* func)(Ts...)) : Call{[func](ASValue::Array arr, ASValue& ret)
        {
            try
            {
                ret = Callback::call_impl(func, std::make_index_sequence<sizeof(...(Ts)>());
                return S_OK;
            } catch (...) {
                return E_INVALIDARG;
            }
        }}
    {}

    std::function<HRESULT(ASValue::Array, ASValue&)> Call;
};

std::index_sequence 是 C++14,但您可能会在 SO 上找到实现。

关于C++ 通用回调实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66329804/

相关文章:

c++ - Qt 托盘图标拖放

c++ - 有没有快速内存访问的技巧?

c++ - 可变参数/非可变参数模板之间的函数类型衰减不一致?

C++ 来自同一个原始指针的多个唯一指针

c++ - 我的 C++ 代码可以编译,但变成了无法运行的无法杀死的程序

C++ 在非 const 指针函数中返回一个 const 指针

c++ - 推导非类型模板参数

匹配 smarty 语法的 javascript 模板引擎

c++ - 有没有办法检测函数是否被覆盖?

templates - 无法解析模板函数的类型