是否有办法使heterogeneous
地图实现如下所示,请满足以下条件:
- 类型在运行时已知,以及读取键。
- 几乎零开销,例如,
boost::any
不是我的目的,这是缓慢的。 没有丑陋的长宏。
class special_map;
class buffer
{
public:
~buffer() = default;
buffer(const special_map& map) : m_map(map) {};
template<typename T>
void read(const std::string& name, T& value)
{
map.read<T>(name, value);
return void();
}
private:
special_map m_map;
};
我可以使用:
void*
加reinterpret_cast
好吗?如何?它对客户端/用户安全吗?- 我可以使用
boost::hana
或boost::fusion
。
谢谢你。(请参见条件)
这是一个内部使用std::map
(或任何您选择的映射实现)的T
类型,我们希望能够存储的实现。从评论中,我读到我们知道我们想要存储什么类型。我期望这个实现的开销与底层映射实现大致相同,但是测试它不是我的工作。在此实现中没有古怪的指针强制转换或使用std::variant等:
#include <map>
template <typename ... T> class special_map {};
template <> class special_map<> {};
template <typename T, typename ... Args> struct MapAccess {};
template <typename T, typename First, typename ...Rest>
struct MapAccess<T, First, Rest...> {
typedef MapAccess<T, Rest...> Next;
static T read(special_map<First, Rest...>* m, const std::string& k) {
return Next::read(&(m->rest), k);
}
static void write(special_map<First, Rest...>* m, const std::string& k, const T& v) {
Next::write(&(m->rest), k, v);
}
};
template <typename T, typename ... Rest>
struct MapAccess<T, T, Rest...> {
static T read(special_map<T, Rest...>* m, const std::string& k) {
return m->storage.at(k);
}
static void write(special_map<T, Rest...>* m, const std::string& k, const T& v) {
m->storage[k] = v;
}
};
template <typename First, typename ... Rest>
struct special_map<First, Rest...> {
special_map<Rest...> rest;
std::map<std::string, First> storage;
template <typename T>
void write(const std::string& k, const T& v) {
MapAccess<T, First, Rest...>::write(this, k, v);
}
template <typename T>
void read(const std::string& k, T& v) {
v = MapAccess<T, First, Rest...>::read(this, k);
}
};
所以要使用它,你必须列出它应该能够存储的所有类型,例如
special_map<float, int, std::string> myMap;
如果您尝试将其与未在该列表中列出的类型一起使用,我希望您会得到一个有趣的编译错误,因此您将知道您必须在那里添加它:-)例如,如果我尝试从myMap
读取bool,我会得到错误
main.cpp:15:22: error: ‘read’ is not a member of ‘MapAccess<bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::Next’ {aka ‘MapAccess<bool>’}