Где я могу найти описание использования "int C :: *"? - PullRequest
8 голосов
/ 31 июля 2011

В фрагменте кода я нахожу что-то вроде:

template<typename T>
class IsClassT {
  private:
    typedef char One;
    template<typename C> static One test(int C::*);
...

Вопрос в том, где я могу найти описание того, почему использование "int C :: *" допустимо в функциональном тесте () определение?

Ответы [ 3 ]

10 голосов
/ 31 июля 2011

int C::* - указатель на член C типа int. Поиск "указатель на член". Раздел стандарта (ISO / IEC 14882: 2003), в котором рассматривается этот синтаксис объявления, - это 8.3.3 Указатели на элементы [dcl.mptr].

Пример использования.

struct Example
{
    int a;
    int b;
};

int test( Example& ex, int Example::* p )
{
    return ex.*p;
}

int main()
{
    Example x = { 3, 5 };
    // Convoluted way of extracting x.a and x.b
    int a = test( x, &Example::a );
    int b = test( x, &Example::b );
}
6 голосов
/ 31 июля 2011

Я не буду описывать, что означает int C::*, поскольку @Charles Bailey уже сделал это очень хорошо. Однако я отвечу на ваш вопрос:

(...) почему использование "int C :: *" допустимо в функции test () определение?

Ключевым моментом является то, что использование int C::* (указатель на член типа int) допустимо тогда и только тогда, когда C является типом класса. В противном случае тип int C::* является плохо сформированным.

Вот почему у вас есть

template<typename C> static One test(int C::*);

и, скорее всего, где-то ниже

template <typename> static Two test(...);
static const bool value = sizeof(test<T>(0)) == 1;

Когда компилятор видит test<T>(0), он проверяет кандидатов на test. Находит два:

template<typename C> static One test(int C::*);   
template <typename> static Two test(...);

Первый имеет приоритет над вторым, потому что 1) они оба являются шаблонными функциями и 2) многоточие ищется последним. Если первый плохо сформирован (т. Е. тогда и только тогда, когда C не является типом класса), то он просто отбрасывается и вторая перегрузка принимается. Это поведение называется SFINAE (для ошибки замены не ошибка).

Проверяя размер возвращаемого типа (помните, что sizeof(char) всегда равен 1), вы можете оценить во время компиляции, что взято test, т.е. * является ли T типом класса или нет.

2 голосов
/ 31 июля 2011

Это указатель на член.
Простой пример понимания Указатель на член .

class A
{
   int a;
   int b;
   void DoSomething();
};

int main()
{
   A *ObjPtr;

   //pointer to member a
   int A::*ptr = &A::a;    

   //Usage
   objPtr->*ptr = NULL;

   //pointer to member function
   void (A::*FuncPtr)(void) = &A::DoSomething; 

   //Usage
   (objPtr->*FuncPtr)(void);    

   return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...