首页 > 解决方案 > 为什么我得到() 函数不能接收元组的子类?

问题描述

我在线复制了一个元组实现,它适用于大多数情况:

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

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

template<size_t, class>
struct elem_type_holder;

template<class T, class... Ts>
struct elem_type_holder<0, tuple<T, Ts...>> {
  typedef T type;
};

template<size_t k, class T, class... Ts>
struct elem_type_holder<k, tuple<T, Ts...>> {
  typedef typename elem_type_holder<k - 1, tuple<Ts...>>::type type;
};

template<size_t k, class... Ts>
typename std::enable_if<
    k == 0, typename elem_type_holder<0, tuple<Ts...>>::type &>::type
get(tuple<Ts...> &t) {
  return t.tail;
}

template<size_t k, class T, class... Ts>
typename std::enable_if<
    k != 0, typename elem_type_holder<k, tuple<T, Ts...>>::type &>::type
get(tuple<T, Ts...> &t) {
  tuple<Ts...> &base = t;
  return get<k - 1>(base);
}

例如,我写了这样的代码:

tuple<int, int, int> mytuple(1, 2, 3);
std::cout << get<1>(mytuple) << std::endl;

“2”将打印。

但是我发现如果我创建一个继承我的自定义元组的子类:

class Foo : public tuple<int, int, int> {
 public:
  Foo() : tuple<int, int, int>(1, 2, 3) {}
};

Foo并为in创建一个对象main()

Foo foo;
td::cout << get<1>(foo) << std::endl;

get()功能将不起作用,错误是:

no matching function for call to ‘get<1>(Foo&)’

然后我测试std::tupleandstd::get()的子类std::tuplestd::get().

目前我必须将它静态转换为元组类而不是传递它,这很烦人。

那么我错过了什么?我怎样才能通过我tuple喜欢的 stl 的子类?

标签: c++c++11

解决方案


g++告诉我们:

<source>:30:6: note:   template argument deduction/substitution failed:
<source>:39:15: note:   'tuple<T, Ts ...>' is an ambiguous base class of 'Foo'
   39 |     get<1>(foo);
      |               ^

这是由以下的递归继承性质引起的:

template <class T, class... Ts>
struct tuple<T, Ts...> : tuple<Ts...> { };

由于编译器不知道要推断什么基类。它可以是tuple<int>tuple<int, int>或中的任何一个tuple<int, int, int>

实际上,将定义更改为...

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

...将使扣除工作。


一种可能的解决方法是将您的元组重新定义为:

template <class T, class... Ts>
struct tuple<T, Ts...> 
{ 
    tuple<Ts...> parent;
};

godbolt.org 上的实时示例


推荐阅读