指向一个模板化函数的不同实例的指针保证比较不相等?

时间:2011-12-29 11:52:13

标签: c++ templates function-pointers

假设指向一个模板化函数的不同实例的两个函数指针将比较不相等是否安全? 即使模板化的函数根本不使用模板参数,因此在每种情况下完全相同的事情?

例如,以下在我的编译器上工作正常,但我不确定它是否适用于任何其他:

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 个答案:

答案 0 :(得分:10)

两个指针何时比较相等?

根据5.10 / 1:

  

==(等于)和!=(不等于)运算符具有相同的值   语义限制,转换和结果类型作为关系   运算符除了较低的优先级和真值结果外。 [   注意:只要a<b == c<da<b具有相同的真值,c<d就为真。 -end note]相同类型的指针(指针转换后)可以   比较平等。两个相同类型的指针比较等于if   并且只有当它们都为空时,都指向相同的函数,或   两者都代表相同的地址(3.9.2)。

foo<int>()foo<char>()功能相同吗?

根据14.4 / 1:

  

如果

,则两个模板ID引用相同的类或函数      
      
  • 他们的模板名称,operator-function-id或literal-operator-id引用相同的模板和
  •   
  • 其对应的类型模板参数属于同一类型
  •   
  • 其对应的整数或枚举类型的非类型模板参数具有相同的值   和
  •   
  • 指针类型的相应非类型模板参数引用相同的外部对象或   函数或都是空指针值和
  •   
  • 它们对应的指向成员类型的非类型模板参数引用同一个类   member或者都是null成员指针值和
  •   
  • 它们对应的引用类型的非类型模板参数引用相同的外部对象   或功能和
  •   
  • 他们对应的模板模板参数引用相同的模板。
  •   

显然foo<int>()foo<char>()的功能不同。

所以无论进行何种优化,&foo<int>()&foo<char>()都不应该相等。


修改

正如@SergeDundich在评论中所提到的,14.4 / 1使用if代替if and only if,这使保证foo<int>()和{{1}是否是相同的功能。在规范的其他部分,foo<char>()被大量使用。

我在规范中没有找到任何澄清。但是,在示例中,我可以找到:

if and only if
     

声明x2和x3属于同一类型。他们的类型不同   x1和x4的类型。


<强> EDIT2:

由于存在这种情况,因此使用

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; 代替if :( 14.5.7 / 2中的示例)

if and only if

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>()的情况,他们的签名是不同的。不同的签名应该使它们具有不同的功能。

感谢@ JohannesSchaub-litb。