C ++ Неоднозначная реализация шаблона для вложенных шаблонных классов variadi c - PullRequest
1 голос
/ 13 марта 2020

Рассмотрим следующее:

template<class... T>
struct outer
{
  template<int... I>
  struct helper{};

  template<int Num, class = helper<>>
  struct inner;
  template<int Num, int... V>
  struct inner<Num,helper<V...>> : public inner<Num-1,helper<V...,sizeof...(V)>>{};
  template<int... V>
  struct inner<0, helper<V...>>{
    using type = helper<V...>;
  };
};

int main(){
  outer<int>::inner<7>::type i;
}

Я обнаружил, что этот код будет компилироваться без ошибок с использованием clang-9.0.1, но не будет работать с использованием g cc -9.2.0 со следующими ошибками:

test2.cpp: In instantiation of ‘struct outer<int>::inner<1, outer<int>::helper<0, 1, 2, 3, 4, 5> >’:
test2.cpp:10:9:   recursively required from ‘struct outer<int>::inner<6, outer<int>::helper<0> >’
test2.cpp:10:9:   required from ‘struct outer<int>::inner<7>’
test2.cpp:18:22:   required from here
test2.cpp:10:9: error: ambiguous template instantiation for ‘struct outer<int>::inner<0, outer<int>::helper<0, 1, 2, 3, 4, 5, 6> >’
   10 |  struct inner<Num,helper<V...>> : public inner<Num-1,helper<V...,sizeof...(V)>>{};
      |         ^~~~~~~~~~~~~~~~~~~~~~~
test2.cpp:10:9: note: candidates are: ‘template<class ... T> template<int Num, int ...V> struct outer<T>::inner<Num, outer<T>::helper<V ...> > [with int Num = 0; int ...V = {0, 1, 2, 3, 4, 5, 6}; T = {int}]’
test2.cpp:12:9: note:                 ‘template<class ... T> template<int ...V> struct outer<T>::inner<0, outer<T>::helper<V ...> > [with int ...V = {0, 1, 2, 3, 4, 5, 6}; T = {int}]’
   12 |  struct inner<0, helper<V...>>{
      |         ^~~~~~~~~~~~~~~~~~~~~~
test2.cpp:10:9: error: invalid use of incomplete type ‘struct outer<int>::inner<0, outer<int>::helper<0, 1, 2, 3, 4, 5, 6> >’
   10 |  struct inner<Num,helper<V...>> : public inner<Num-1,helper<V...,sizeof...(V)>>{};
      |         ^~~~~~~~~~~~~~~~~~~~~~~
test2.cpp:8:9: note: declaration of ‘struct outer<int>::inner<0, outer<int>::helper<0, 1, 2, 3, 4, 5, 6> >’
    8 |  struct inner;
      |         ^~~~~
test2.cpp: In function ‘int main()’:
test2.cpp:18:24: error: ‘type’ is not a member of ‘outer<int>::inner<7>’
   18 |  outer<int>::inner<7>::type i;
      |   

Я видел похожее рекурсивное наследование, преуспевающее в g cc, но, похоже, это не так, когда оно находится внутри шаблона класса variadi c. Также следует отметить, что изменение внешнего шаблона на template<class T> исправляет ошибки g cc.

Это ошибка clang или g cc?

...