Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointers to different instances of one templated function guaranteed to compare unequal?

Is it safe to assume that two function pointers, that point to different instances of one templated function, will compare unequal? Even if the templated function does not use the template parameter(s) at all and thus does the exact same thing in every case?

For example the following works fine on my compiler but I'm not sure if it does on any other:

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
}
like image 689
Baltram Avatar asked Dec 29 '11 11:12

Baltram


1 Answers

When will two pointer compare equal?

According to 5.10/1:

The == (equal to) and the != (not equal to) operators have the same semantic restrictions, conversions, and result type as the relational operators except for their lower precedence and truth-value result. [ Note: a<b == c<d is true whenever a<b and c<d have the same truth-value. —end note ] Pointers of the same type (after pointer conversions) can be compared for equality. Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address (3.9.2).

Are foo<int>() and foo<char>() the same function?

According to 14.4/1:

Two template-ids refer to the same class or function if

  • their template-names, operator-function-ids, or literal-operator-ids refer to the same template and
  • their corresponding type template-arguments are the same type and
  • their corresponding non-type template arguments of integral or enumeration type have identical values and
  • their corresponding non-type template-arguments of pointer type refer to the same external object or function or are both the null pointer value and
  • their corresponding non-type template-arguments of pointer-to-member type refer to the same class member or are both the null member pointer value and
  • their corresponding non-type template-arguments of reference type refer to the same external object or function and
  • their corresponding template template-arguments refer to the same template.

So apparently foo<int>() and foo<char>() are not the same function.

So &foo<int>() and &foo<char>() should not compare equal, whatever optimization is made.


EDIT:

As mentioned by @SergeDundich in the comment, 14.4/1 used if instead if and only if, which gives no guarantee whether foo<int>() and foo<char>() are the same function or not. In other parts of the specification, if and only if is used a lot.

I didn't find any clarification to this in the specification. However, in the examples, I can find this:

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;

declares x2 and x3 to be of the same type. Their type differs from the types of x1 and x4.


EDIT2:

if is used instead of if and only if as this situation exists: (Example from 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> and vector<int, Alloc<int>> have a lot of differences, but still the same type.

However, as to the case of foo<int>() and foo<char>(), their signatures are different. The different signatures should render them different functions.

Thanks to @JohannesSchaub-litb .

like image 88
fefe Avatar answered Oct 06 '22 12:10

fefe