6

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

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

我还有一个模板化函数,我希望它接受这些结构的成员之一,splatted:

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. 我还有其他选择吗?

4

1 回答 1

1

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

但是,您可以通过重载获得类似的功能,这更容易实现。例如,您可以call_func为您的类型定义重载的 a:

#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++ 中是不可能的。

于 2019-06-14T12:53:31.910 回答