2016-08-30 4 views
3

この標準変換に関する既存の質問を読んだことがあります。 しかし、満足のいく回答は見つかりませんでした。テンプレート型減算が暗黙の配列からポインタへの変換を実行します

このコードは、T*のオーバーロードがT&&よりも大きいことを示しています。私が理解したところから、別のオーバーロードが完全に一致しない限り、転送参照のオーバーロードはすべてをバインドする必要があります。

次のコードでは、tabchar const(&)[4]です。

誰かがここで配列からポインタへの変換が実行される理由を説明できますか? その変換を回避する方法がある場合、私はすべての耳です!

(coliru link

#include <utility> 

template <typename T> 
void f(T&& lol) 
{ 
} 

template <typename T> 
void f(T* pof) 
{ 
    static_assert(sizeof(T) && false, ""); 
} 

template <typename T> 
struct S; 

int main(int argc, char *argv[]) 
{ 
    decltype("lol") tab = "lol"; 
    S<decltype(tab)> s; 
    f("lol"); 
    return 0; 
} 
+0

関連/重複を::

これを解決するために、我々はSFINAE使用して、たとえば、コンパイラへf(T*)はあまり魅力的にする必要がhttp://stackoverflow.com/q/28182838は、http://// 21972652。 –

答えて

5

配列はタイプPTRと推定されます。 Aの場合はA)

1)Pは、参照型ではない場合:

は控除を開始する前に、PとAと次の調整が が行われhttp://en.cppreference.com/w/cpp/language/template_argument_deduction

参照します配列型、Aは配列からポインタへの変換で得られたポインタ型に置き換えられます。

b)Aが関数型である場合、Aは関数からポインタへの変換によって得られたポインタ型に置き換えられます。

C)Aは、CV-修飾型であればそうでない場合は、トップレベルのCV-修飾子は単一引数の関数テンプレートfをテンプレートg場合よりも、より専門的な考えられている控除

+0

奇妙なことは、 'T const(&)[N]'オーバーロードを加えた後でさえ、呼び出しが曖昧であると言ってコンパイルに失敗します。ポインタと配列を区別する方法はありませんか? – Dante

+0

これを試すことができます:http://stackoverflow.com/questions/28182838/is-it-possible-to-overload-a-function-that-c​​an-tell-a-fixed-array-from-a-pointer – Hayt

+0

両方とも、提案された回避策が動作します。非常にトリッキーですが、それは私に合っています – Dante

3

では無視されますfの引数に対応する任意の型は、gの引数に導くことができますが、その逆はできません。

任意のポインタ型T*T&&に推定することができるが、これは逆方向に保持していない(T&&は、一般的な場合にT*に推定することができない)ので、f(T*)f(T&&)より特殊であると考えられます。

template <typename U, 
    typename T = std::enable_if_t<std::is_pointer<U>::value, std::remove_pointer_t<U>>> 
void f(U const& pof) // U == T* 
関連する問題