在問題How can I detect if a type can be streamed to an std::ostream?之後,我寫了一個特徵類,說明某種類型是否可以流式傳輸到IO流。直到現在我發現了一個問題,這個特質似乎運作良好。爲什麼我的特徵模板類查找運算符<< for llvm :: StringRef?
我使用的是使用LLVM的項目中的代碼,我使用它們的StringRef類(它與提議的std :: string_view類似)。 Here是Doxygen文檔的類的鏈接,如果需要,可以從中找到它的聲明頭文件。由於LLVM不提供運算符將StringRef對象傳送到標準流(它們使用自定義的輕量級流類),因此我寫了一個。
然而,當我使用的特點這是行不通的,如果我的運營商定製< <聲明後性狀(出現這種情況,因爲我有一個頭的特點和操作< <功能的另一個) 。我曾經認爲模板實例化中的查找是從實例化點的角度來看的,所以我認爲它應該起作用。其實,正如你可以在下面看到的那樣,另一個類和它的自定義運算符< <,在特徵後面聲明,一切都按預期工作(這就是爲什麼我現在才發現這個問題),所以我無法弄清楚是什麼讓StringRef特別。
這是完整的例子:
#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 的聲明它打印真實。 那麼爲什麼會發生這種奇怪的事情,我該如何解決這個問題?
將您的操作符置於與啓用ADL的類型相同的命名空間中。 – Yakk
@Yakk這就是答案,那麼爲什麼不寫一個呢? – jrok
@jrok因爲我正在給寶寶睡覺睡覺,這並不妨礙檢查它是真正的問題和詳細說明等。:) – Yakk