【问题标题】:Is there a way to hold many type of pointer to function without reinterpret_cast?有没有办法在没有 reinterpret_cast 的情况下保存多种类型的函数指针?
【发布时间】:2018-02-01 13:56:45
【问题描述】:

我有一些代码可以处理许多指向不同签名函数的指针。这是一个sn-p:

#include <unordered_map>

// Simple type id system
template<typename> void type_id(){}
using type_id_t = void(*)();

// value type of our map. We reinterpret functions pointer to this type
using held_type = void(*)();

// actual function type.
template<typename T>
using funct_type = T(*)();

int main() {
    std::unordered_map<type_id_t, held_type> function_map;

    function_map.emplace(type_id<int>, reinterpret_cast<held_type>(
        static_cast<func_type<int>>([]() -> int { return 42; });
    ));

    function_map.emplace(type_id<double>, reinterpret_cast<held_type>(
        static_cast<func_type<double>>([]() -> double { return 9.4; });
    ));

    // later on

    // prints 42
    std::cout << reinterpret_cast<func_type<int>>(function_map[type_id<int>])();

    // prints 9.4
    std::cout << reinterpret_cast<func_type<double>>(function_map[type_id<double>])();
}        

有没有一种方法可以在没有大量开销和重新解释强制转换的情况下获得类似的结果?

【问题讨论】:

  • 您绝对可以通过编写适当的提取方法来完成大部分工作来缩短它,但是完全摆脱花哨的演员表可能是不可能的。
  • 想象有一个解决方案。编译器如何知道function_map[key]() 的返回类型而不自己指定呢?任何函数调用的返回类型必须在编译时知道,但在这种情况下,它将取决于key 的值和function_map 的状态,它们是运行时信息。在这种情况下,键恰好是从类型名称派生的。如果您更改示例,例如使用enum 作为键,它可能会被清除。
  • 你能改变函数声明还是固定的?否则,您可以反转方法并始终使用相同的声明。在这种情况下不再需要强制转换。
  • @VTT 我会很高兴只使用static_cast。问题是,reinterpret_cast 更难维护和捕获错误。 @FrançoisAndrieux 不幸的是,我不能使用枚举,我有不确定数量的用户定义类型。
  • @GuillaumeRacicot 是的,可能是this。 :-) ...好吧,我把它放在一个答案中。希望对你有帮助。

标签: c++ function-pointers reinterpret-cast


【解决方案1】:

如果您可以对函数进行一些修改,则可以通过反转流程并删除返回类型来处理它。
这是我的意思的一个例子:

#include <unordered_map>
#include <iostream>

template<typename T>
void call(T t, void *ptr) {
    *static_cast<T *>(ptr) = t;
}

// Simple type id system
template<typename> void type_id() {}
using type_id_t = void(*)();

// value type of our map. We reinterpret functions pointer to this type
using held_type = void(*)(void *);

// actual function type.
template<typename T>
using funct_type = T(*)();

int main() {
    std::unordered_map<type_id_t, held_type> function_map;

    function_map.emplace(type_id<int>, +[](void *ptr){ return call(42, ptr); });
    function_map.emplace(type_id<double>, +[](void *ptr) { call(9.4, ptr); });

    // prints 42
    int i;
    function_map[type_id<int>](&i);
    std::cout << i << std::endl;

    // prints 9.4
    double d;
    function_map[type_id<double>](&d);
    std::cout << d << std::endl;
}

wandbox 上查看并运行它。

当您查询function_map 时,您可能可以使用变量的类型来选择type_id 的正确特化。只需将所有内容隐藏在函数模板后面即可。

【讨论】:

    猜你喜欢
    • 2021-02-20
    • 2021-09-24
    • 2018-08-02
    • 2022-01-14
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    相关资源
    最近更新 更多