Отрывок, обеспеченный 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);
}
Это - острота, также;)
Не могли бы вы попробовать?
template<typename T>
int do_outer(T& val)
{
return val.get_inner().template get<int>();
}
У меня нет доступа к gcc atm, но у меня были похожие проблемы, и добавление ключевого слова template всегда решало их. И в VS тоже работает.
Просто чтобы дать некоторую справку о том, почему необходимо ключевое слово 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
является объектом или функцией. (
устраняет неоднозначность между этими двумя и имя рассматривается как функция. Позже вывод аргументов шаблона затем определяет тип параметра шаблона.
Я не могу утверждать, что являюсь одним из 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.