C++11 标记元组

标签 c++ c++11 tuples

C++11 元组很好,但它们对我来说有两个巨大的缺点,通过索引访问成员是

  1. 不可读
  2. 难以维护(如果我在元组中间添加一个元素,我就完蛋了)

本质上我想要实现的是这个

tagged_tuple <name, std::string, age, int, email, std::string> get_record (); {/*...*/}
// And then soomewhere else

std::cout << "Age: " << get_record().get <age> () << std::endl;

在 boost::property_map 中实现了类似的东西(类型标记),但我不知道如何在具有任意数量元素的元组中实现它

PS 请建议使用元组元素索引定义枚举。

UPD 好的,这是一个动机。在我的项目中,我需要能够“即时”定义许多不同的元组,并且所有元组都需要具有某些通用函数和运算符。这是结构无法实现的

UPD2 实际上,我的示例实现起来可能有点不切实际。这个怎么样?

tagged_tuple <tag<name, std::string>, tag<age, int>, tag<email, std::string>> get_record (); {/*...*/}
// And then somewhere else

std::cout << "Age: " << get_record().get <age> () << std::endl;

最佳答案

我不知道有任何现有的类可以做到这一点,但是使用 std::tuple 和索引类型列表很容易将一些东西放在一起:

#include <tuple>
#include <iostream>

template<typename... Ts> struct typelist {
  template<typename T> using prepend = typelist<T, Ts...>;
};

template<typename T, typename... Ts> struct index;
template<typename T, typename... Ts> struct index<T, T, Ts...>:
  std::integral_constant<int, 0> {};
template<typename T, typename U, typename... Ts> struct index<T, U, Ts...>:
  std::integral_constant<int, index<T, Ts...>::value + 1> {};

template<int n, typename... Ts> struct nth_impl;
template<typename T, typename... Ts> struct nth_impl<0, T, Ts...> {
  using type = T; };
template<int n, typename T, typename... Ts> struct nth_impl<n, T, Ts...> {
  using type = typename nth_impl<n - 1, Ts...>::type; };
template<int n, typename... Ts> using nth = typename nth_impl<n, Ts...>::type;

template<int n, int m, typename... Ts> struct extract_impl;
template<int n, int m, typename T, typename... Ts>
struct extract_impl<n, m, T, Ts...>: extract_impl<n, m - 1, Ts...> {};
template<int n, typename T, typename... Ts>
struct extract_impl<n, 0, T, Ts...> { using types = typename
  extract_impl<n, n - 1, Ts...>::types::template prepend<T>; };
template<int n, int m> struct extract_impl<n, m> {
  using types = typelist<>; };
template<int n, int m, typename... Ts> using extract = typename
  extract_impl<n, m, Ts...>::types;

template<typename S, typename T> struct tt_impl;
template<typename... Ss, typename... Ts>
struct tt_impl<typelist<Ss...>, typelist<Ts...>>:
  public std::tuple<Ts...> {
  template<typename... Args> tt_impl(Args &&...args):
    std::tuple<Ts...>(std::forward<Args>(args)...) {}
  template<typename S> nth<index<S, Ss...>::value, Ts...> get() {
    return std::get<index<S, Ss...>::value>(*this); }
};
template<typename... Ts> struct tagged_tuple:
  tt_impl<extract<2, 0, Ts...>, extract<2, 1, Ts...>> {
  template<typename... Args> tagged_tuple(Args &&...args):
    tt_impl<extract<2, 0, Ts...>, extract<2, 1, Ts...>>(
      std::forward<Args>(args)...) {}
};

struct name {};
struct age {};
struct email {};

tagged_tuple<name, std::string, age, int, email, std::string> get_record() {
  return { "Bob", 32, "bob@bob.bob"};
}

int main() {
  std::cout << "Age: " << get_record().get<age>() << std::endl;
}

您可能希望在现有访问器之上编写 const 和右值 get 访问器。

关于C++11 标记元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13065166/

相关文章:

c++ - std::error_code,my_error::check_block == my_error::validate && my_error::accept_block == my_error::validate

c++ - 我应该在哪里指定 [[gnu::transparent_union]]?

c# - 如何在 C# 中调用元组

c++ - 为什么定义没有返回类型的 main() 编译没有错误?

c++ - C 位标志枚举应如何转换为 C++?

C++11 正则表达式分组

c++ - 元组和可变参数模板,这是如何工作的?

python - 使用 psycopg2 从 python 中的元组中提取字符串

python - 如何将 vtkSphere 保存到 VTK 文件?

c++ - 如何使用 STL 排序函数根据第二列对二维数组进行排序?