Nach der Frage How can I detect if a type can be streamed to an std::ostream? habe ich eine Merkmalsklasse geschrieben, die besagt, ob ein Typ in einen IO-Stream gestreamt werden kann. Das Merkmal scheint bis jetzt gut zu funktionieren, dass ich ein Problem entdeckt habe.Warum kann mein Trait Template-Klassen-Suchoperator << für llvm :: StringRef nicht?
Ich verwende den Code in einem Projekt, das LLVM verwendet, und ich benutze ihre StringRef-Klasse (die im Sinne der vorgeschlagenen std :: string_view ähnlich ist). Here ist ein Link zum Doxygen-Dokument für die Klasse, von dem Sie bei Bedarf die Deklarationsheaderdatei finden können. Da LLVM keinen Operator < < zum Streamen von StringRef-Objekten an Std-Streams bereitstellt (sie verwenden eine benutzerdefinierte Lightweight Stream-Klasse), habe ich eine geschrieben.
Allerdings, wenn ich das Merkmal verwenden funktioniert es nicht, wenn mein benutzerdefinierter Operator < < nach das Merkmale erklärt wird (dies geschieht, weil ich das Merkmal in einem Header und die Bediener habe < < Funktion in einer anderen) . Ich dachte früher, dass das Nachschlagen in Template-Instanziierungen vom Standpunkt des Instanziierungspunkts aus funktioniert, also dachte ich, es sollte funktionieren. Wie Sie unten sehen können, funktioniert eine andere Klasse und ihr benutzerdefinierter Operator < < nach dem Merkmal, alles funktioniert wie erwartet (deshalb habe ich dieses Problem erst jetzt entdeckt), also kann ich nicht herausfinden, was StringRef ausmacht Besondere.
Dies ist die komplette Beispiel:
#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;
}
Entgegen meinen Erwartungen, diese Drucke:
false
true
Wenn ich die Erklärung des Betreibers < < für StringRef vor die Eigenschaft Erklärung bewegen , es druckt wahr. Also warum passiert dieses seltsame Ding und wie kann ich dieses Problem beheben?
Setzen Sie Ihren Operator in denselben Namespace wie den Typ, um ADL zu aktivieren. – Yakk
@Yakk Das ist die Antwort, also warum nicht eine schreiben? – jrok
@jrok, weil ich ein Baby für ein Nickerchen schlafen legen, und das ist nicht günstig zu überprüfen, es ist das echte Problem und Ausarbeitung usw. :) – Yakk