2014-01-09 7 views
18

は、私は生のポインタで動作するテンプレートがあるとします。テンプレート以外の過負荷を削除するよりも、テンプレートインスタンシエーションを削除するのはいつですか?

template<typename T> 
void processPointer(T* ptr); 

私はこれがvoid*ポインタと呼ばれるようにしたくありません。私には2つの選択肢があるようです。

void processPointer(void*) = delete; 

または私はテンプレートのインスタンスを削除することができます:

template<> 
void processPointer<void>(void*) = delete; 

は、非テンプレート過負荷(角括弧付きなしfutzing)が容易である宣言を私は非テンプレート過負荷を削除することができます。代わりにテンプレートのインスタンス化を削除する理由がありますか?

+1

+1、私は答えを自分でわからないので。テンプレートのインスタンス化を削除するのは、テンプレート全体のオーバーロードを考える傾向があるからです。後で、コードを読むとき(つまり、最小の驚きの原則に従う)、何が起こっているのかを理解する方が簡単だと思います。私は、何かを選択する技術的な理由があるかどうかはわかりません。 – utnapistim

答えて

4

Iは、非テンプレート過負荷を削除することによって、あなたは私が右を考えることはできませんいくつかのエッジケースあいまいな呼び出しのあなたの方法を小刻みに動くことがあり、実際にはここに

をテンプレーティング行くために何らかの理由が表示されません非テンプレートがテンプレートのインスタンス化よりも優先されるためです。したがって、大部分の場合、この作業を必要に応じて行います。

4

これは、洞察力を与える可能性があります

#include <iostream> 

struct X 
{ 
    template<typename T> 
    void processPointer(T* ptr) { 
     std::cout << "Template\n"; 
    } 

    // error: explicit specialization in non-namespace scope ‘struct X’ 
    // template<> 
    // void processPointer(void*) = delete; 

    // Overload but no specialization 
    // This will prevent lookup the specialization outside the class, when no 
    // template argument is explicitly given. However, with an explicit 
    // template argument the specialization is called. 
    void processPointer(void*) = delete; 
}; 

// Specialization outside the class body 
template<> 
void X::processPointer(void* ptr) { 
    std::cout << "Specialization\n"; 
} 

int main() 
{ 
    X x; 
    //error: use of deleted function ‘void X::processPointer(void*)’ 
    //x.processPointer((void*)0); 

    // Explicit template argument: 
    x.processPointer<void>((void*)0); 
} 

結論:@Caseyの答えが成り立ちます。

+2

あなたはどのような洞察をすると思いますか? (私は思う*私は知っているが、あなたが実際には言わなかったので、私は確信していない。コードが説明しているものを繰り返し記入してください) –

+1

'template <> void X :: processPointer (void *)= delete; '[クラススコープの外部に特殊化することができます](http://coliru.stacked- crooked.com/a/d5e781c971aa54b0 "Coliruのデモコード")。 – Casey

16

Here's one reasonテンプレートバージョン:processPointer<void>(void*)は、他のオーバーロードを回避して、直接呼び出すことができます。

+2

+1テンプレート引数を明示的に指定するのは、ジェネリックコードではかなり一般的です。 –

0

はあなたprocessPointer機能にタイプvoid*(または単にnullptr)の引数pointerを通過したいとあなたはまた、タイプTypeために、その専門性を呼び出したいとします。そして、あなたは

void processPointer(void*) = delete; 

ため

processPointer(static_cast<Type>(pointer)); 

を書く必要があります。しかし

template<> 
void processPointer<void>(void*) = delete; 

のためにあなたは非常に短いコードを書くことができます:

processPointer<Type>(pointer); 

だから、両方の変形が可能に異なる場合に使用される。

しかし、非テンプレート過負荷の変異体のアナログは、場合によっては唯一の方法である可能性があります。あなたはそれが最初の引数としてvoid*ポインタと呼ばれるようにしたくない

template<typename T, typename U> 
void processPointer(T* ptr1, U* ptr2); 

: は、2つのパラメータを持つ関数テンプレートがあるとします。

template<typename U> 
void processPointer<void, U>(void*, U*) = delete; 

そして、あなたは別のものを使用する必要があります:関数テンプレートの部分特殊化はので、このコードが間違っているC++で許可されていません

template<typename U> 
void processPointer(void*, U*) = delete; 
関連する問題