質問に従って、タイプを std::ostream にストリーミングできるかどうかを検出するにはどうすればよいですか? あるタイプを IO ストリームにストリーミングできるかどうかを示す特性クラスを作成しました。この特性は、私が問題を発見した今までうまく機能しているように見えました。
私はLLVMを使用するプロジェクト内のコードを使用しており、StringRefクラスを使用しています(提案されたstd::string_viewと精神的に似ています)。クラスの Doxygen doc へのリンクを次に示します。必要に応じて、宣言ヘッダー ファイルを見つけることができます。LLVM は、StringRef オブジェクトを std ストリームにストリーミングする operator<< を提供しないため (カスタムの軽量ストリーム クラスを使用します)、1 つ作成しました。
ただし、トレイトを使用する場合、カスタム operator<< がトレイトの後に宣言されていると機能しません (これは、あるヘッダーにトレイトがあり、別のヘッダーに operator<< 関数があるために発生します)。テンプレートのインスタンス化でのルックアップは、インスタンス化ポイントの観点から機能すると考えていたので、機能するはずだと考えました。実際、以下に示すように、別のクラスとそのカスタム operator<< をトレイトの後に宣言すると、すべてが期待どおりに機能します (そのため、この問題を発見したのは今だけです)。特別な。
これは完全な例です:
#include <iostream>
#include "llvm/ADT/StringRef.h"
// Trait class exactly from the cited question's accepted answer
template<typename T>
class is_streamable
{
template<typename SS, typename TT>
static auto test(int)
-> decltype(std::declval<SS&>() << std::declval<TT>(),
std::true_type());
template<typename, typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<std::ostream,T>(0))::value;
};
// Custom stream operator for StringRef, declared after the trait
inline std::ostream &operator<<(std::ostream &s, llvm::StringRef const&str) {
return s << str.str();
}
// Another example class
class Foo { };
// Same stream operator declared after the trait
inline std::ostream &operator<<(std::ostream &s, Foo const&) {
return s << "LoL\n";
}
int main()
{
std::cout << std::boolalpha << is_streamable<llvm::StringRef>::value << "\n";
std::cout << std::boolalpha << is_streamable<Foo>::value << "\n";
return 0;
}
私の予想に反して、これは次のように表示されます。
false
true
特性宣言の前に StringRef の operator<< の宣言を移動すると、 true が出力されます。では、なぜこの奇妙なことが起こっているのでしょうか?どうすればこの問題を解決できますか?