C ++-右辺値参照による関数テンプレート特化の動作

c++ c++11 enable-if rvalue-reference template-specialization
C ++-右辺値参照による関数テンプレート特化の動作

条件付きポインターの逆参照関数を実装しようとしています。 基本的な考え方は次のとおりです。

return is_pointer(arg) ? *arg : arg
必要な特殊化の数を制限するために、 `arg`がポインターではない場合に右辺値参照を使用しようとしています。 これが私の現在の実装です( `std

cout`はデバッグ目的のためだけにあります):

template< typename T >
inline typename std::enable_if< std::is_pointer< T >::value == false, T >::type deref(T&& t)
{
    std::cout << std::is_pointer< T >::value << std::endl;
    std::cout << typeid (T).name() << std::endl;
    return t;
}

template< typename T >
inline typename std::enable_if< std::is_pointer< T >::value == true, typename std::remove_pointer< T >::type& >::type deref(T t)
{
    std::cout << std::is_pointer< T >::value << std::endl;
    std::cout << typeid (T).name() << std::endl;
    return *t;
}

さて、GCC 4.6ではかなり奇妙な動作になります。 最初のオーバーロードは、非ポインター型とポインター型の両方に使用されます。 明らかに、ポインター型を使用する場合、2番目のオーバーロードと競合します。 2番目のコメントをコメントアウトし、最初のコメントを使用して以下を呼び出すと…​

int q;
int *p = &q;
deref(p);
  1. 対応するコンソール出力は次のとおりです。

0
Pi
( `std

is_pointer`による)非ポインター型が、同じコンテキストで(` typeid`による)ポインター型でもあることはどのように可能ですか? std :: is_pointer`が誤って p`を非ポインター型として報告するため、両方のオーバーロード間で競合が発生します。 また、最初のオーバーロードでr値参照を標準参照に置き換えた場合:

inline typename std::enable_if< std::is_pointer< T >::value == false, T >::type deref(T& t)

もう2番目のオーバーロードと競合しません…​ 私は単に何が起こっているのか分かりません。 ちなみに、2番目のオーバーロードを使用すると(予想どおり)生成されます。

1
Pi

ご協力いただきありがとうございます。

  1  0


ベストアンサー

私が理解する限りでは

template
void foo(T&&)

つまり、 T`が左辺値である場合、それは参照(あなたの場合は T = int *& )として推論され、参照後は int * &&& の折りたたみにより通常の左辺値参照 int *& `が生成されます。 そうでない場合、この構文は右辺値参照として何でもキャプチャします。 その点は、左辺値を左辺値参照にバインドし、右辺値を右辺値参照にバインドすることです。

そして、 `is_pointer`は正しくありません。 したがって、 `remove_reference`を適用してみてください。

3


最初のオーバーロードでは、Tはint *&として推定されます。 enable_if-testingおよび出力で `remove_reference

type`を使用する最初のオーバーロードで試してください。

2


タイトルとURLをコピーしました