Определение функции шаблона члена вне строки с использованием другой функции шаблона члена в подписи

Я столкнулся с этой проблемой в каком-то реальном коде C ++ 11, но я свел ее к следующему:

template<int i> struct Dummy {};

template<typename T>
struct Foo {
  template<int i> static constexpr int bar() { return i; }

  template<int i>
  static auto working() -> Dummy<bar<i>()>;

  template<int i>
  static auto also_working() -> Dummy<Foo<T>::template bar<i>()>;

  template<int i>
  static Dummy<Foo<T>::template bar<i>()> not_working();
};

template<typename T> template<int i>
auto Foo<T>::working() -> Dummy<bar<i>()> {
  return Dummy<bar<i>()>{};
}

template<typename T> template<int i>
auto Foo<T>::also_working() -> Dummy<Foo<T>::template bar<i>()> {
  return Dummy<bar<i>()>{};
}

template<typename T> template<int i>
Dummy<Foo<T>::template bar<i>()> Foo<T>::not_working() {
  return Dummy<bar<i>()>{};
}

Я пытался создать внеочередное определение функция-член шаблона класса шаблона, где сигнатура функции включала вызов другой функции-члена шаблона и начиналась с чего-то вроде функции not_working(). Проблема заключалась в том, что определение не соответствовало декларации.

Clang сказал:

clang++ -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -std=c++11   -c -o out_of_line.o out_of_line.cc
out_of_line.cc:28:42: error: out-of-line definition of 'not_working' does not match any declaration in 'Foo<T>'
Dummy<Foo<T>::template bar<i>()> Foo<T>::not_working() {
                                         ^~~~~~~~~~~

GCC сказал:

g++ -Wall -Wextra -pedantic -std=c++11   -c -o out_of_line.o out_of_line.cc
out_of_line.cc:28:34: error: prototype for ‘Dummy<bar<i>()> Foo<T>::not_working()’ does not match any in class ‘Foo<T>’
 Dummy<Foo<T>::template bar<i>()> Foo<T>::not_working() {
                                  ^~~~~~
out_of_line.cc:14:43: error: candidate is: template<class T> template<int i> static Dummy<Foo<T>::bar<i>()> Foo<T>::not_working()
   static Dummy<Foo<T>::template bar<i>()> not_working();
                                       ^~~~~~~~~~~

Методом проб и ошибок я обнаружил, что используя конечный тип возврата, я могу получить определение, соответствующее объявлению, что приводит к функция also_working(). Оказавшись там, я понял, что из-за изменения области видимости в конечном типе возврата я мог отказаться от некоторой квалификации имени, получив гораздо более красивую функцию working().

Теперь мне интересно, почему функция not_working() не работает, то есть почему ее определение не совпадает с ее объявлением (я мог бы просто остаться в неведении относительно решения, которое я нашел, но я, скорее всего, столкнусь с большим количеством такого рода проблемы, и я не хочу тратить больше времени, используя метод проб и ошибок); лежит ли ошибка в компиляторах или в моем коде. Я прочитал 14.6 Разрешение имен [temp.res] , но я не уверен, какие правила применимы для этого случая.

Пояснение вопроса : Учитывая правила в стандарте C ++ 11:

  1. , должно ли определение not_working() соответствовать объявлению?
  2. какие правила участвуют в определении 1.?
  3. , как правила из 2. взаимодействуют при определении 1.?
10
задан psyill 15 May 2017 в 19:52
поделиться