g ++ не любит шаблонное объединение в цепочку метода на шаблонном var?

Отрывок, обеспеченный Lex, был немного длинен, таким образом, я указываю на важную часть, так как никто больше не использовал ту же самую технику:

string MethodName = new StackFrame(0).GetMethod().Name;

Это должно возвратить идентичные результаты MethodBase. GetCurrentMethod () техника.Name , но на это все еще стоит указать, потому что я мог реализовать это однажды в его собственном методе с помощью индекса 1 для предыдущий метод и назвать его от многих различных свойств. Кроме того, это только возвращает один кадр скорее тогда все отслеживание стека:

private string GetPropertyName()
{  //.SubString(4) strips the property prefix (get|set) from the name
    return new StackFrame(1).GetMethod().Name.Substring(4);
}

Это - острота, также;)

5
задан Rômulo Ceccon 15 October 2009 в 20:04
поделиться

3 ответа

Не могли бы вы попробовать?

template<typename T>
int do_outer(T& val)
{
  return val.get_inner().template get<int>();
}

У меня нет доступа к gcc atm, но у меня были похожие проблемы, и добавление ключевого слова template всегда решало их. И в VS тоже работает.

8
ответ дан 18 December 2019 в 09:08
поделиться

Просто чтобы дать некоторую справку о том, почему необходимо ключевое слово template :

template<typename T>
int do_outer(T& val)
{
  int i;
  val.get_inner().get<int>(i);
  return i;
}

Когда компилятор видит эту функцию, он не знает, какой тип val есть. Поэтому он анализирует строку val.get_inner (). Get (i) следующим образом:

1: val.

Компилятор видит . и поэтому можно предположить, что 'val' имеет тип класса, а следующий идентификатор - это имя объекта-члена или функции.

2. вал. get_inner (

get_inner - это имя члена, а затем компилятор видит (. Единственная возможность состоит в том, что get_inner - это имя функции, и поэтому это вызов функции. Затем он анализирует параметры, пока не найдет закрывающую ) .

3. val. get_inner ().

Что касается первого шага, теперь он знает, что возврат от get_inner должен быть типом класса, поэтому он знает, что следующий идентификатор является объектом-членом или функцией.

4. вал. get_inner (). get <

Итак, что может означать <? Конечно, это начало аргументов шаблона ... или, может быть, это оператор «меньше»?

Мы знаем, что get может быть только объектом или функцией. Если это объект, то < имеет смысл как оператор «меньше». Кроме того, в стандарте более или менее указано, что только в том случае, если имя перед < является именем шаблона , он будет рассматривать < как аргументы шаблона (14.2 / 3):

После поиска имени (3.4) обнаруживает, что имя является именем шаблона, если за этим именем следует <, то < всегда используется как начало списка аргументов-шаблонов и никогда не используется как имя, за которым следует оператор «меньше».

В этом случае компилятор не знает, какой тип выражения val.get_inner () , и поэтому он не может выполнить поиск get . Это более или менее предполагает, что это объект-член, а не имя шаблона. «<» рассматривается как оператор «меньше чем», и компилятор проверяет, меньше ли get , чем int - отсюда и ошибка.

Итак, почему исправления работают?

Добавление шаблона ключевое слово

Буквально мы сообщаем компилятору, что get - это имя шаблона, поэтому < Оператор рассматривается как начало списка аргументов шаблона.

Удаление аргументов шаблона

Когда do_outer не имеет аргументов шаблона, например: val. get_inner (). get ( компилятор ожидает, что член get является объектом или функцией. ( устраняет неоднозначность между этими двумя и имя рассматривается как функция. Позже вывод аргументов шаблона затем определяет тип параметра шаблона.

11
ответ дан 18 December 2019 в 09:08
поделиться

Я не могу утверждать, что являюсь одним из 10 человек на планете, которые полностью понимают шаблоны C ++, но то, что вы здесь делаете, мне нравится. (Он не работает с GCC 4.4.1 с той же ошибкой, BTW).

Изменение do_outer на

const Inner& inner = val.get_inner();
return inner.get<int>();

работает с GCC и, предположительно, также будет работать с Visual C ++.

Вы можете рассмотреть возможность регистрации. ошибка с GCC; либо они исправят это, либо он будет закрыт как НЕДЕЙСТВИТЕЛЬНЫЙ, и в процессе кто-то, надеюсь, объяснит, почему то, что вы делаете, не является правильным кодом.

Дальнейшее обновление и AHA: Оказывается, это на самом деле неправильный код , GCC просто выдает ужасное сообщение об ошибке. Intel C ++ выводит (действительно полезное!) Сообщение об ошибке:

template.cpp(24): error: type name is not allowed
    return val.get_inner().get<int>();

Что заставило меня понять проблему. При изменении do_inner на

  return val.get_inner().template get<int>();

код принимается как ICC, так и GCC.

-1
ответ дан 18 December 2019 в 09:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: