c++ - C++11 中的模板化映射 vector

标签 c++ templates c++11 hashmap

我正在尝试做一些我认为最初应该微不足道的事情,但遇到了关于我应该如何理想地构建它的设计问题。我想创建一个存储一堆参数的键值对映射。这里的“key”始终是一个字符串。但是该值可以是 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 中的模板化映射 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30677255/

相关文章:

c++ - 编译器会优化模板 bool 吗?

c++ - C++中模板的原理是什么?

c++ - 所有 CopyConstructible 类型都是 MoveConstructible 类型吗?

c++ - 这是冲突吗?关于 C++ 汽车

每个可用于匿名集合的 C++?

c++ - 可以在多重映射中搜索元素吗?需要吗?

c++ - &*x 操作是否创建拷贝?

c++ - 模板参数推导失败

C++ 内联程序集试图将 char 从 std::string 复制到寄存器中

c++ - 对表示为结构体的函数进行部分求值