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

C++ 指向一个模板函数的不同实例的指针是否保证比较不相等?,c++,templates,function-pointers,C++,Templates,Function Pointers,假设指向一个模板化函数的不同实例的两个函数指针会比较不相等,安全吗? 即使模板化函数根本不使用模板参数,因此在每种情况下都执行完全相同的操作 例如,以下内容在我的编译器上运行良好,但我不确定是否在任何其他编译器上运行良好: class TypeChecker { public: template< typename T > static void foo( void ) {} template< typename T > static void s

假设指向一个模板化函数的不同实例的两个函数指针会比较不相等,安全吗? 即使模板化函数根本不使用模板参数,因此在每种情况下都执行完全相同的操作

例如,以下内容在我的编译器上运行良好,但我不确定是否在任何其他编译器上运行良好:

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
}
类类型检查器
{
公众:
模板静态void foo(void)
{}
模板静态void setType(void)
{s_fooPtr=&foo}
模板静态bool checkType(void)
{return(s_fooPtr==&foo);}
私人:
静态空隙(*s_fooPtr)(空隙);
};
void(*TypeChecker::s_fooPtr)(void)=0;
内部主(空)
{
类型检查器::setType();
TypeChecker::checkType();//true
TypeChecker::checkType();//false
TypeChecker::checkType();//false
}

两个指针何时比较相等?

根据5.10/1:

==(等于)和!=(不等于)运算符具有相同的 语义限制、转换和结果类型作为关系 运算符,但其优先级和真值结果较低。[
注意:
a关于3.9.2中的“函数”是什么?该措辞在某种程度上暗示函数是一个有地址的对象。@fefe:“两个模板ID引用同一个类或函数if”,但不是“if”和“if”和“only if”。您注意到了吗?我认为这非常重要。我的结论是“
foo()
foo()“
不是同一个函数”是错误的。标准显然不要求它们是同一个函数,但你的引用并不能证明它们不是同一个函数。@sharptooth:在3.9.2/2中,指针分为
对象指针类型
函数指针类型
。对象指针类型定义为“指向void的指针或指向对象类型的指针的类型称为对象指针类型。”,然而,“可以指定函数的指针类型称为函数指针类型。”规范似乎在避免使用“指向函数的指针”“对于函数指针。在后一种情况下,只有对象指针类型表示
表示内存中字节的地址(1.7)或空指针(4.10)。
@SergeDundich:将在答案中添加注释。规范确实使用了”if And only if“很多。例如,使用a=B
a
B
模板可以引用同一个类。但在这两种情况下,模板名称并不引用同一个模板(因此“if”而不是“if and only if”很重要)。但是,别名模板解析为的类型将引用14.5.7和14.4/1中的同一类。
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;
template<class T> struct Alloc { /* ... */ };
template<class T> using Vec = vector<T, Alloc<T>>;
Vec<int> v; // same as vector<int, Alloc<int>> v;