【问题标题】:c++ templates add member of certain type to classc ++模板将某种类型的成员添加到类
【发布时间】:2017-11-27 18:39:06
【问题描述】:

我想创建一个 c++ 类,我可以在其中添加类型(int、long、double、string)的成员。我对 C++ 中的模板编程非常陌生。

我一直在关注本指南:https://eli.thegreenplace.net/2014/variadic-templates-in-c/ 用于可变参数数据结构。但是如何输入类型(int、long 等)及其值并将该成员添加到我的类中?

例如,如果这是我定义元组类的方式:

template <class... Ts> struct tuple {};

template <class T, class... Ts>
struct tuple<T, Ts...> : tuple<Ts...> {
  tuple(T t, Ts... ts) : tuple<Ts...>(ts...), tail(t) {}

  T tail;
};

然后我想在运行时接受输入并且:

while(cin>>type) {
  cin>>value;
  // add type and value to my class
}

输入可能是int 3 double 3.5 string hello。 在这种情况下,我的班级应该是tuple&lt;int, double, std::string&gt; t(3, 3.5, "hello")

有没有办法使用模板编程来实现这一点?

【问题讨论】:

  • 简短回答:否。
  • @StoryTeller 如果我将类型限制为std::string,那么我可以继续向班级添加成员吗?
  • 那还是不行。元组的类型必须静态地知道。有一些技术可以在运行时处理未知类型。但是你不能随意给一个类类型添加成员。
  • 您可以在运行时将成员添加到类中,例如如果您的语言称为 Python。在 C++ 中,您使用 std::vector&lt;std::variant&lt;int,long,double,std::string&gt;&gt;

标签: c++ templates variadic-templates template-meta-programming


【解决方案1】:

如果您真的想根据来自cin 的信息使用静态类型,例如std::tuple&lt;int, int, char, int&gt; 那么您的编译器必须“准备”所有可能编译时的路径。根据类型的数量N 和最大长度s,有 不同的可能性,即可能性的数量随着最大长度s 呈指数增长。对于非常小的Ns 这可以工作。由于您可能更喜欢另一种方法(没有静态类型,例如std::tuple&lt;int, int, char, int&gt;),我准备了一个仅处理类型的C++17示例。

#include <cstdint>
#include <iostream>
#include <tuple>

template<
  class F,
  class Tuple=std::tuple<>
>
auto tuplify_cin_and_call(
  F f,
  Tuple tuple=Tuple{}
) {
  constexpr std::size_t max_tuple_size = 6;

  std::cout << __PRETTY_FUNCTION__ << std::endl;

  if constexpr(1 + std::tuple_size<Tuple>::value < max_tuple_size) {
    std::cout << "`int`|`char` to append or `done` to finish: " << std::flush;
    std::string input{};
    std::cin >> input;

    if(input == std::string{"int"}) {
      tuplify_cin_and_call(f, std::tuple_cat(tuple, std::tuple<int>{}));
    }
    else if(input == std::string{"char"}) {
      tuplify_cin_and_call(f, std::tuple_cat(tuple, std::tuple<char>{}));
    }
    else if(input == std::string{"done"}) {
      return f(std::move(tuple));
    }
    else {
      std::cout << "ERROR: invalid input" << std::endl;// `cout` or `cerr` here?
      return tuplify_cin_and_call(f, std::move(tuple));
    }
  }
  else {
    std::cout << "max size reached. `done` to finish: " << std::flush;

    std::string input{};
    std::cin >> input;

    if(input == std::string{"done"}) {
      return f(std::move(tuple));
    }
    else {
      std::cout << "ERROR: invalid input" << std::endl;// `cout` or `cerr` here?
      return tuplify_cin_and_call(f, std::move(tuple));
    }
  }
}

int main() {
  tuplify_cin_and_call(
    [] (auto tuple) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  );
  return 0;
}

输出(包括我的键盘输入):

./main
auto tuplify_cin_and_call(F, Tuple) [with F = main()::<lambda(auto:1)>; Tuple = std::tuple<>]
`int`|`char` to append or `done` to finish: int 
auto tuplify_cin_and_call(F, Tuple) [with F = main()::<lambda(auto:1)>; Tuple = std::tuple<int>]
`int`|`char` to append or `done` to finish: char
auto tuplify_cin_and_call(F, Tuple) [with F = main()::<lambda(auto:1)>; Tuple = std::tuple<int, char>]
`int`|`char` to append or `done` to finish: asdf
ERROR: invalid input
auto tuplify_cin_and_call(F, Tuple) [with F = main()::<lambda(auto:1)>; Tuple = std::tuple<int, char>]
`int`|`char` to append or `done` to finish: char char int
auto tuplify_cin_and_call(F, Tuple) [with F = main()::<lambda(auto:1)>; Tuple = std::tuple<int, char, char>]
`int`|`char` to append or `done` to finish: auto tuplify_cin_and_call(F, Tuple) [with F = main()::<lambda(auto:1)>; Tuple = std::tuple<int, char, char, char>]
`int`|`char` to append or `done` to finish: auto tuplify_cin_and_call(F, Tuple) [with F = main()::<lambda(auto:1)>; Tuple = std::tuple<int, char, char, char, int>]
max size reached. `done` to finish: asdf
ERROR: invalid input
auto tuplify_cin_and_call(F, Tuple) [with F = main()::<lambda(auto:1)>; Tuple = std::tuple<int, char, char, char, int>]
max size reached. `done` to finish: done
main()::<lambda(auto:1)> [with auto:1 = std::tuple<int, char, char, char, int>]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-25
    • 2019-04-12
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多