喷涂结构

时间:2019-06-14 02:16:03

标签: c++ struct initializer-list splat variable-templates

我有一堆这样的结构,其中成员数量不断增加,但成员命名却保持一致:

struct one { int a; };
struct two { int a; int b; };
struct three { int a; int b; int c; };

我还有一个模板化函数,我想接受以下结构的成员之一:

template <typename T, typename ... ARGS> // T will be one, two, or three
void func(ARGS... args); // This should take 1, 2, or 3, int arguments respectively

我希望能够这样称呼它:

two foo;

func<two>(splatter(foo));

splatter会以某种方式拆分foo,以便解析为func<two>(foo.a, foo.b)

很明显,我可以不用splatter来扩展此内联代码,但是我调用func的代码本身很容易被模板化。我尝试使用initializer_list,但是我不知道如何仅基于模板类型来构建一个。

不幸的是,我的编译器也不支持constexpr if来发起对func的调用或构建initializer_list。我还有其他选择吗?

1 个答案:

答案 0 :(得分:1)

据我所知,您所描述的内容无法使用c ++完成。或者,如果可以的话,那将是一个非常复杂的解决方案。原因是,您需要以某种方式存储指向类成员访问函数的指针,然后使用实际对象正确调用它们。

但是,您可以通过重载获得类似的功能,该功能易于实现。例如,您可以定义一个call_func,以便为您的类型重载:

#include <array>

// types
struct one {
  int a;
};
struct two {
  int a;
  int b;
};
struct three {
  int a;
  int b;
  int c;
};
template <class T>
struct more_complex_type {
  T a;
  T b;
};
// template function
template <typename T, typename... ARGS>
auto func(ARGS... args) {
  return std::array<T, sizeof...(args)>{args...};
}
// indirection overload
template <class T>
struct call_func_impl {};
template <>
struct call_func_impl<one> {
  auto call(one val) { return func<int>(val.a); }
};
template <>
struct call_func_impl<two> {
  auto call(two val) { return func<int>(val.a, val.b); };
};
template <>
struct call_func_impl<three> {
  auto call(three val) { return func<int>(val.a, val.b, val.c); };
};
template <class T>
struct call_func_impl<more_complex_type<T>> {
  auto call(more_complex_type<T> val) { return func<T>(val.a, val.b); };
};
// syntacting sugar
template <class T>
auto call_func(T val) {
  return call_func_impl<T>{}.call(val);
}
// tests
auto test_func() { return func<int>(1, 2, 3, 4, 5); }
auto test_func_of_one() {
  auto val = one{};
  return call_func(val);
}
auto test_func_of_two() {
  auto val = two{};
  return call_func(val);
}
auto test_func_of_three() {
  auto val = three{};
  return call_func(val);
}
auto test_func_of_more_complex_type() {
  auto val = more_complex_type<double>{};
  return call_func(val);
}

此示例使用重载的结构模板包装函数调用。对于您的情况,这可能不是必需的,因为您没有模板类型。实际上,您可以重载call_func。但是,这种方法允许您定义对more_complex_type的调用,该调用已被模板化,因为在c ++中当前无法实现部分函数重载。