3

非メンバーメソッドが定義されているかどうかに応じて、テンプレートを特殊化する方法を知っている人はいますか?メンバー関数が存在するかどうかを特殊化する方法はたくさんあることは知っていますが、非メンバーの例を見たことがありません。特定の問題は、shared_ptrのoperator <<を特殊化して、operator<<がTに定義されている場合はoperator<<を適用し、それ以外の場合は単なるポインター位置を出力することです。すべてのクラスがoperator<<をメンバーとして定義していれば素晴らしいのですが、残念ながら多くのクラスが無料の関数を使用しています。私は次のようなものを想像しています:

template <typename T>
typename enable_if< ??? ,std::ostream &>::type operator<<( std::ostream & os, const shared_ptr<T> & ptr )
{
  if(ptr)
   return os << *ptr;
  else
   return os << "<NULL>";
}

template <typename T>
typename disable_if< ??? ,std::ostream &>::type operator<<( std::ostream & os, const shared_ptr<T> & ptr )
{
  if(ptr)
   return os << static_cast<intptr_t>( ptr.get() );
  else
   return os << "<NULL>";
}

編集:後世のために、ここに実用的な解決策がありました。boost :: shared_ptrには、アドレスを出力するデフォルトの演算子<<がすでにあるため、disable_ifは不要であることに注意してください。operator <<は参照を返すため、これは機能します。一般的なケースでは、問題の関数の戻り値のタイプを反映するようにこれを調整する必要があると思います。

template <typename T>
typename boost::enable_if_c< boost::is_reference<decltype(*static_cast<std::ostream *>(0) << *static_cast<T *>(0) )>::value, std::ostream &>::type operator<<( std::ostream & os, const boost::shared_ptr<T> & ptr )
{
  if(ptr)
   return os << *ptr;
  else
   return os << "<NULL>";
}
4

1 に答える 1

2

C ++ 0xを使用している場合は、単にdecltypeを使用できます。

template<typename Char, typename CharTraits, typename T>
        decltype(
            *(std::basic_ostream<Char, CharTraits>*)(nullptr) << *(T*)(nullptr)
        )

Tを出力できない場合は、確実に置換エラーが発生します。おそらくC++03でも同様のことができますが、その方法はわかりません。

編集:decltype式は実際にはtrueまたはfalseの値を生成せず、コンパイルされないことに気づきました。しかし、あなたは絵を手に入れます。これを試して。

于 2010-07-30T22:08:10.917 に答える