重新解释没有类型标识符的 cast void

Reinterpret cast void without type identifier

我正在使用类型擦除(void cast)在一对一映射中存储多个基本类型(float、bool、int 等)。重新解释原始数据类型的一种方法是使用 pair/union/class 来存储带有类型标识符(例如 pair)的值。有没有一种干净的方法可以在没有 Boost 的情况下使用 C++11 解析没有标识符的基本类型?

std::map<int, void *> m_mymap;
// avoid std::map<int, pair<void, MyEnum> > m_mymap;

template <class T> void setValue<T>(int i_key, T i_val)
{
    m_mymap[i_key] = reinterprete_cast<void *>(i_val);
}

template <class T> T getValue<T>(int i_key)
{
    return reinterprete_cast<T>(i_val);
}

doSomeWork()
{
    for (const auto & elem : m_mymap)
    {
        auto val = some_magical_cast< ??? >(elem.second) // resolve type without a nasty switch against MyEnum 
        // do some work
    }
}

编辑:更新问题以使用 void *

auto val = some_magical_cast< ??? >(elem.second) // resolve type without a nasty switch against MyEnum 

C++ 是一种静态 类型的语言。必须在编译时知道每种类型。您要执行的操作需要根据放入地图的内容在 运行时 确定类型。

这在 C++ 中是不可能的。 val 必须具有单一的特定类型,而不是通过执行运行时代码确定的类型。并且循环的每次迭代都必须给它相同的类型。联合或 variant 将允许您存储在运行时确定的几种类型之一。但是它们存储的类型集在编译时是固定的。

即使 auto val 可能以某种方式产生一系列不同的类型,void* 也不包含任何可用于恢复其指向的类型的信息。请注意 boost/std::any 也没有任何恢复此类型的能力;你必须要求一个特定的类型(区别在于如果你要求错误的类型,any 将失败,而 void* 会给你 UB)。

所以不,这是不可能的。

正如@NicolBolas 正确解释的那样,你不能。

作为可行的approach/workaround,您可以使用基于双重调度思想的技术,如下例所示:

#include<map>
#include<utility>
#include<iostream>

class C {
public:
    template<typename T>
    void accept(int k, T v) { std::cout << k << " " << v << std::endl; }
};

using P = void(*)(C &, int, void *);

std::map<int, std::pair<P, void*>> m;

template<typename T>
void proto(C &c, int k, void *v) {
    c.accept(k, *static_cast<T*>(v));
}

template <class T>
void set(int k, T *v) {
    m[k] = { &proto<T>, v };
}

void get(C &c, int k) {
    auto p = m[k];
    p.first(c, k, p.second);
}

int main() {
    int i = 42;
    double d = 1.2;

    set(0, &i);
    set(1, &d);

    C c;
    for(auto &&k: m) {
        get(c, k.first);
    }
}

它需要额外的 class(示例中的 C)。
您可以为不同的类型添加 class 不同的方法(例如,您可以使用两种接受 intdouble 的方法来代替模板方法)。
这样,您既可以拥有通用行为,也可以拥有许多特定类型的行为。

当然,它更复杂,而且不是免费的,否则你无法得到你想要的。