Указатели на разные экземпляры одной шаблонной функции гарантированно сравнивают неравные? - PullRequest
12 голосов
/ 29 декабря 2011

Можно ли предположить, что два указателя на функцию, которые указывают на разные экземпляры одной шаблонной функции, будут сравниваться неравно?Даже если шаблонная функция вообще не использует параметр (ы) шаблона и, таким образом, выполняет одинаковую функцию в каждом случае?

Например, следующее работает нормально на моем компиляторе, но я не уверен, что онделает по любому другому:

class TypeChecker
{
public:
    template< typename T > static void foo( void )
    {}
    template< typename T > static void setType( void )
    { s_fooPtr = &foo< T >; }
    template< typename T > static bool checkType( void )
    { return ( s_fooPtr == &foo< T > ); }
private:
    static void ( * s_fooPtr )( void );
};

void ( * TypeChecker::s_fooPtr )( void ) = 0;

int main( void )
{
    TypeChecker::setType< char >();
    TypeChecker::checkType< char >();           // true
    TypeChecker::checkType< unsigned char >();  // false
    TypeChecker::checkType< signed char >();    // false
}

1 Ответ

10 голосов
/ 29 декабря 2011

Когда два указателя будут сравниваться равными?

Согласно 5.10 / 1:

== (равно) и! = (Неравно) операторы имеют те же семантические ограничения, преобразования и тип результата, что и реляционные операторы, за исключением их более низкого приоритета и истинностного результата.[Примечание: a<b == c<d истинно, когда a<b и c<d имеют одно и то же значение истинности.- примечание конца] Указатели одного типа (после преобразования указателей) можно сравнивать на равенство.Два указателя одного типа сравниваются равными, если и только если они оба равны нулю, оба указывают на одну и ту же функцию, или оба представляют один и тот же адрес (3.9.2).

Являются ли foo<int>() и foo<char>() одинаковыми функциями?

Согласно 14.4 / 1:

Два идентификатора шаблона относятся к одному и тому же классу илифункция, если

  • их имена шаблонов, идентификаторы операторов или литералы операторов ссылаются на один и тот же шаблон, а
  • их аргументы шаблона соответствующего типа:один и тот же тип и
  • соответствующие им нетипизированные аргументы шаблона целочисленного типа или типа перечисления имеют идентичные значения, а
  • соответствующие им нетипизированные аргументы шаблона типа указателя ссылаются на одно и то жевнешний объект или функция, либо оба являются нулевым значением указателя, а
  • их соответствующие нетипизированные аргументы шаблона типа указатель на член относятся к одному и тому же члену класса или оба являются нулевым значением указателя на член и
  • соответствующие им нетипизированные аргументы шаблона ссылочного типа ссылаются на тот же внешний объект или функцию, а
  • соответствующие им аргументы шаблона ссылаются на тот же шаблон.

Так что, очевидно, foo<int>() и foo<char>() не являются одной и той же функцией.

Так что &foo<int>() и &foo<char>() не должны сравниваться одинаково, независимо от того, какая оптимизация выполнена.


РЕДАКТИРОВАТЬ:

Как упомянуто @SergeDundich в комментарии, 14,4 / 1 использовал if вместо if and only if, что дает нет гарантию того, foo<int>() и foo<char>() - это одна и та же функция или нет.В других частях спецификации часто используется if and only if.

Я не нашел никакого объяснения этому в спецификации.Однако в примерах я могу найти это:

template<class T, void(*err_fct)()> class list { /* ... */ };
list<int,&error_handler1> x1;
list<int,&error_handler2> x2;
list<int,&error_handler2> x3;
list<char,&error_handler2> x4;

объявляет x2 и x3 одинакового типа.Их тип отличается от типов x1 и x4.


EDIT2:

if используется вместоif and only if, поскольку такая ситуация существует: (Пример из 14.5.7 / 2)

template<class T> struct Alloc { /* ... */ };
template<class T> using Vec = vector<T, Alloc<T>>;
Vec<int> v; // same as vector<int, Alloc<int>> v;

Vec<int> и vector<int, Alloc<int>> имеют много различий, но все еще одного типа.

Однако, что касается foo<int>() и foo<char>(), их подписи разные.Разные подписи должны предоставлять им разные функции.

Благодаря @ JohannesSchaub-litb.

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