有没有办法在没有 reinterpret_cast 的情况下保存多种类型的函数指针?

Is there a way to hold many type of pointer to function without reinterpret_cast?

我有一些代码处理许多指向不同签名函数的指针。这是一个片段:

#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>])();
}        

有没有一种方法可以实现类似的结果而无需大量开销且无需重新解释转换?

如果您可以稍微修改一下您的函数,您可以通过反转流程并删除 return 类型来实现它。
这是我的意思的一个例子:

#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 的正确特化。只需将所有内容隐藏在函数模板之后。