2011-12-29 6 views
12

1つのテンプレート関数の異なるインスタンスを指し示す2つの関数ポインタが等しくないと仮定するのは安全でしょうか? テンプレート化された関数がテンプレートパラメータをまったく使用しない場合でも、まったく同じことが起こります。テンプレート化された関数の異なるインスタンスへのポインタは、等しくないと保証されますか?

は、例えば以下は、私のコンパイラで正常に動作しますが、私は、他にそれがないかどうかわからないんだけど:

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 
} 

答えて

10

2つのポインタが等しいとなりますか? 5.10/1によれば

==(等しい)と=(等しくない)演算子は、リレーショナル と同じ意味上の制限、変換、及び結果のタイプを持っています!演算子の優先順位と真理値の結果が低いことを除けば、 [ 注:a<bc<dの真偽値が同じ場合は、a<b == c<dが真になります。 -end note]同じタイプのポインタ(ポインタの変換後)は、同等であると比較して にすることができます。同じタイプの2つのポインタは、 の場合は等しいとみなし、両方がヌルの場合にのみ、は両方とも同じ関数を指します。または は両方とも同じアドレス(3.9.2)を表します。

foo<int>()foo<char>()は同じ機能ですか? 14.4/1によれば

二テンプレートIDは、同じクラスまたは関数を参照する場合

  • そのテンプレートの名前、オペレータ機能IDS、またはリテラルオペレータ-idsは同じテンプレートを参照し、と
  • の対応するタイプのテンプレート引数が同じタイプであることを示します。一体型または列挙型のnding非型テンプレート引数は、ポインタ型のそれらの対応する非型テンプレート引数が同一の外部オブジェクトまたは 機能を指す同じ値 と
  • を有するか、または両方のヌルポインタ値と
  • あります対応する非メンバ型のテンプレート型引数が同じクラス メンバを参照しているか、nullメンバポインタ値であり、
  • 参照型の対応する非型テンプレート引数が、同じ外部オブジェクト または機能
  • 対応するテンプレートtemplate-argumentsは同じテンプレートを参照します。

だから、明らかにfoo<int>()foo<char>()同じ機能ではありません。

したがって、&foo<int>()&foo<char>()は、最適化が行われても同等である必要はありません。


EDIT:

コメントで@SergeDundichにより述べたように、14.4/1 foo<int>()foo<char>()が同じ機能であるか否かない保証を与える、if and only if代わりifを用います。本明細書の他の部分では、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で使用される:

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>>(14.5.7/2の例)がたくさんあります違いはありますが、それでも同じタイプです。

ただし、foo<int>()foo<char>()の場合は、署名が異なります。異なる署名は、それらを異なる機能にするはずです。

@ JohannesSchaub-litbに感謝します。

+0

3.9.2の「機能」についてはどうですか?その言い回しは、何らかの形で関数がアドレスを持つオブジェクトであることを意味します。 – sharptooth

+1

@fefe: "2つのテンプレートIDは、同じクラスまたは関数を参照しています** **"ただし、 "if only" if。それに気づいた? IMOそれは非常に重要です。そして、IMOは、 "foo ()'と 'foo ()'は同じ関数ではないという結論は間違っています。彼らは明らかに標準によって同じ機能である必要はありませんが、あなたの引用は同じ機能ではないことを証明していません**。 –

+0

@sharptooth:3.9.2/2では、ポインタは「オブジェクトポインタ型」と「関数ポインタ型」に分かれています。オブジェクト・ポインタ型は、「** void型へのポインタの型**またはオブジェクト型へのポインタ**はオブジェクト・ポインタ型と呼ばれます」と定義されますが、「**指定可能なポインタの型**関数は関数ポインタ型と呼ばれます。仕様が関数ポインタのための "ポインタ"の使用を避けているようだ。後者では、オブジェクトポインタ型だけが 'メモリ内のバイトのアドレス(1.7)またはヌルポインタ(4.10)のいずれかを表します。 – fefe

関連する問題