Недавно я попытался создать класс is_class
и потребовал, чтобы компилятор мог различать типы перечислений и типы классов, для которых определены операторы преобразования. Учитывая, что классы, структуры и объединения являются единственными типами, совместимыми с функциями-указателями-членами, я решил, что компилятор определит, был ли тип, используемый для создания экземпляра шаблона is_class
, в свою очередь, совместим с указателями- функции-члены. После нескольких проблем, я решил проверить поведение перечислений при использовании в сочетании с указателями между собой и получил некоторые дурацкие результаты. Следующий сегмент иллюстрирует первый приступ:
enum ENUM {};
void Test(void (ENUM::*pmem) (void))
{
/* ... */
}
Test(NULL);
При компиляции с Microsoft Visual С++ 2010 часть указателя на элемент определения функции: (ENUM::*pmem)
выделяется красным цветом, а mousing над объявлением обнаруживает ошибку:
Error: "ENUM" is not a class type
Однако компилятор анализирует этот сегмент без каких-либо ошибок, присваивая pmem
NULL
. Мне интересно, что компилятор разрешил бы это видеть, как типы перечисления не являются классами, структурами или объединениями и поэтому не могут обладать собственными методами.
Вторая интересная задача возникла при создании функции шаблона, взяв аргумент-указатель-член, тип которого варьируется:
template<class _Ty>
void Test_Template(void (_Ty::*pmem) (void))
{
/* ... */
}
Конечно, чтобы использовать эту функцию, она должна быть явно определена:
Test_Template<ENUM>(NULL);
Этот вызов, однако, генерирует сообщение об ошибке:
invalid explicit template argument(s) for 'void Test(void (__thiscall _Ty::* )(void))'
Я исправил эту проблему, создав дополнительный шаблон функции, прототип которого соответствовал бы любому вызову, который не соответствовал прототипу предыдущей функции шаблона (в которой использовалось многоточие).
Вопросы:
-
Почему перечисление совместимо с указателями-членами?
-
Почему существует точное совпадение при вызове функции non-template
Test
, когда компилятор генерирует ошибку для явной квалификации шаблонаTest_Template
?