gpt4 book ai didi

c++ - C++11 中模板化 map 的 vector

转载 作者:搜寻专家 更新时间:2023-10-31 02:22:06 25 4
gpt4 key购买 nike

我正在尝试做一些我认为最初应该是微不足道的事情,但是我遇到了关于我应该如何理想地构建它的设计问题。我想创建一个存储一堆参数的键值对映射。这里的“键”总是一个字符串。但是,该值可以是 int、double、string 或 char。我有枚举来定义类型:

typedef enum {INT = 0, DOUBLE, STRING, CHAR} val_type;

我正在考虑将其构造为 map vector

std::vector<std::map<std::string, T>> params;

最有原则的方法是什么?

编辑:更新了 vector 声明。

最佳答案

我有 15 分钟。传入标记 union 。不如boost::variant ,我可能不会真正编译它,但它应该可以帮助您入门。

template<size_t S>
using size = std::integral_constant<std::size_t, S>;
template<bool b>
using bool_t = std::integral_constant<bool, b>;

template<size_t...Ss>
struct max_size:size<0>{};
template<size_t S0, size_t...Ss>
struct max_size:size<(std::max)(S0, max_size<Ss...>{}())>{};

template<class...Ts>
struct max_alignof : max_size< alignof(Ts)... >{};
template<class...Ts>
struct max_sizeof : max_size< sizeof(Ts)... >{};


template<class X>struct tag{using type=X;};
template<class...>struct types{using type=types;};
template<class Tag>using type_t=typename Tag::type;

template<class T, class Types>
struct index_of {};
template<class T, class...Ts>
struct index_of<T, types<T,Ts...>>:size<0>{};
template<class T, class T0, class...Ts>
struct index_of<T, types<T0,Ts...>>:size<
index_of<T, types<Ts...>>{}+1
>{};

template<class X>
struct emplace_as {};

template<class F, class...Ts>
void invoke( types<Ts...>, void* p, F&& f, size_t i ) {
auto* pf = std::addressof(f);
using operation=void(*)(decltype(pf), void*);
operation table[]={
+[](decltype(pf), void* p){
Ts* pt = static_cast<Ts*>(p);
std::forward<F>(*pf)( *pt );
}...
};
table[i]( pf, p );
}

template<class T0, class...Ts>
struct one_of {
std::aligned_storage< max_sizeof<T0, Ts...>{}, max_alignof<T0, Ts...>{} > data;
size_t index = -1;
using my_types = types<T0, Ts...>;
template<class T>
using sfinae_my_type = tag< size<index_of<X,my_types>{}> >;

one_of():one_of(emplace_as<T0>{}) {}

// brace construction support for only the first type:
one_of(T0&&t0):one_of(emplace_as<T0>{}, std::move(t0)) {}

template<class X, class...Args, class=sfinae_my_type<X>>
one_of(emplace_as<X>, Args&&... args){
emplace( emplace_as<X>{}, std::forward<Args>(args)... );
}
template<class X, class=sfinae_my_type<std::decay_t<X>>>
one_of(X&& x) {
emplace_as(std::forward<X>(x));
}
template<class X, class=sfinae_my_type<X>>
X* get() {
if (index_of<X, my_types>{}==index) {
return static_cast<X*>(&data);
} else {
return nullptr;
}
}
template<class X, class=sfinae_my_type<X>>
X const* get() const {
if (index_of<X, my_types>{}==index) {
return static_cast<X const*>(&data);
} else {
return nullptr;
}
}

template<class X, class=sfinae_my_type<std::decay_t<X>>>
void emplace(X&& x) {
emplace_as<std::decay_t<X>>{}, std::forward<X>(x));
}

template<class X, class...Args, class=sfinae_my_type<X>>
void emplace( emplace_as<X>, Args&&...args ) {
destroy();
new(&data) X(std::forward<Args>(args)...);
index = index_of<X, list<T0, Ts...>>{};
}

template<class F>
void my_invoke(F&& f) {
my_invoke( std::forward<F>(f), index );
}
template<class F>
void apply(F&& f) {
invoke( my_types{}, &data, std::forward<F>(f), index );
}
void destroy() {
if (index != -1) {
apply([&](auto&& x){
using X=std::decay_t<decltype(x)>;
index = -1;
x.~X();
});
};
}

one_of& operator=(one_of const& rhs){
if (this == &rhs) return *this;
destroy();
rhs.apply( [&](auto const& x) {
using X=std::decay_t<decltype(x)>;
emplace( emplace_as<X>{}, decltype(x)(x) );
} );
return *this;
}
one_of& operator=(one_of&& rhs){
if (this == &rhs) return *this;
destroy();
rhs.apply( [&](auto & x) {
using X=std::decay_t<decltype(x)>;
emplace( emplace_as<X>{}, std::move(x) );
} );
return *this;
}
~one_of(){destroy();}
};

这是标记 union 类型的快速草图。

存储 one_of<int, double, std::string, char>作为你的T .通过 apply 访问传入一个函数,每个函数都有覆盖,或 get<T> .

上面是C++14,因为它更容易。它不包括 apply有一个返回值,同样是因为它使它更容易。两者都可以补救,但需要努力,真的,你应该看看如何boost这样做而不是使用上面的方法。

关于c++ - C++11 中模板化 map 的 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30677255/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com