как удалить const из сигнатуры шаблона функции-члена? - PullRequest
4 голосов
/ 25 марта 2011

Я работаю над некоторыми системными вещами типа C ++, и у меня возникают проблемы с удалением константности из функции-члена для использования с классами функций. Что действительно вызывает сомнения, так это то, что с G ++ это прекрасно работает, но MSVC10 не может правильно обрабатывать частичную специализацию, и я не знаю, есть ли здесь какой-либо из этих компиляторов.

Вопрос здесь в том, как правильно удалить квалификатор const из функции-члена таким образом, чтобы я мог получить сигнатуру типа функции?

Возьмите следующий пример кода:

  #include <iostream>

  template<typename T> struct RemovePointer { typedef T Type; };
  template<typename T> struct RemovePointer<T*> { typedef T Type; };
  template<typename R,typename T> struct RemovePointer<R (T::*)> { typedef R Type; };

  class A {
  public:
     static int StaticMember() { return 0; }
     int Member() { return 0; }
     int ConstMember() const { return 0; }
  };

  template<typename T> void PrintType(T arg) {
     std::cout << typeid(typename RemovePointer<T>::Type).name() << std::endl;
  }

  int main()
  {
     PrintType(&A::StaticMember);
     PrintType(&A::Member);
     PrintType(&A::ConstMember); // WTF?
  }

Все три этих оператора PrintType должны печатать одно и то же. MSVC10 печатает следующее:

int __cdecl(void)
int __cdecl(void)
int (__cdecl A::*)(void)const __ptr64

g ++ печатает это (что является ожидаемым результатом):

FivE
FivE
FivE

Ответы [ 3 ]

3 голосов
/ 25 марта 2011

Я предлагаю вам взглянуть на TypeTraits.h библиотеки loki Александреску. Он предоставляет общий способ удаления квалификаторов, например, const.

http://loki -lib.cvs.sourceforge.net / локи Пб / локи / включить / локи / TypeTraits.h? Вид = Разметка

Когда у меня возникают философские проблемы с метапрограммированием метапрограммирования с ++, я склонен заглядывать в современный дизайн с ++, если есть ответ для моего местонахождения.

1 голос
/ 25 марта 2011

typeid(...).name() возвращает строку, определяемую реализацией. Это может быть искаженный компилятором символ или стихотворение, написанное Джоном Скитом. Пожалуйста, не полагайтесь на это, чтобы сделать что-нибудь полезное.

Также странно хотеть снять с него "const"; функция равна const, так почему бы вам не добавить это в результирующую строку?

Понятия не имею, почему вы ожидаете или видите «FIVE». Я не вижу ничего подобного в вашем коде.

1 голос
/ 25 марта 2011

Это поможет:

template<typename R,typename T> struct RemovePointer<R (T::*)() const> { typedef R Type; };

Обратите внимание, что вы, вероятно, также хотите добавить () в предыдущую строку (в противном случае оно будет соответствовать как указателям на члены, так и указателям на функции):

template<typename R,typename T> struct RemovePointer<R (T::*)()> { typedef R Type; };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...