Страницы

Поиск по вопросам

воскресенье, 22 декабря 2019 г.

Вопрос по SFINAE

#cpp #шаблоны_с++


При прочтении книги возник вопрос по коду:

template 
struct IsClass {
template  static True isClass( int C::* );
template  static False isClass( ... );
enum { r = sizeof(IsClass::isClass(0))
== sizeof(True) };
};


Почему код корректно работает на любых классах, вне зависимости от того есть или
нет члены типа int, хотя в шаблоне функции static True isClass( int C::* ) аргумент
указатель на член класса типа int?
    


Ответы

Ответ 1



Тут всё довольно просто, при компиляции с каким-либо типом, эта строчка: template static True isClass( int C::* ); превращается во что-то такое: static True isClass( int Type::* ); Теперь, если Type это какой-то встроенный тип, эта функция отбраковывается (для того, чтобы объявить указатель на член, тип должен быть классом). Если же Type является классом (любым), тогда это функция компилируется нормально, ведь вне зависимости от того, есть ли вообще в классе какие-либо члены, мы можем создать указатель на член. К примеру: void* std::string::* ptr; Другой вопрос, что нам нечем этот член инициализировать (ничего реального нет, кроме nullptr), но это уже дело десятое. Главное, что мы его объявили. Теперь мы можем передать туда nullptr или 0. Декларация в C++ вообще требует очень мало: чтобы использовать какой-то класс в контексте, где знание о его внутреннем устройстве и размере необязательно, достаточно вот такой предварительной декларации: class SomeClass; И теперь можете создавать указатели на SomeClass, указатели на функции SomeClass или, как в вопросе, указатели на поля SomeClass. Это поведение гарантировано стандартом C++ и описано в разделе [dcl.mptr]

Комментариев нет:

Отправить комментарий