Theo câu hỏi How can I detect if a type can be streamed to an std::ostream? Tôi đã viết một lớp đặc điểm cho biết nếu một số loại có thể được phát trực tiếp tới luồng IO. Đặc điểm này dường như hoạt động tốt cho đến bây giờ mà tôi đã phát hiện ra một vấn đề.Tại sao toán tử tra cứu lớp mẫu tra cứu đặc điểm của tôi << đối với llvm :: StringRef?
Tôi đang sử dụng mã bên trong một dự án sử dụng LLVM và tôi đang sử dụng lớp StringRef của họ (tương tự như tinh thần với đề xuất std :: string_view). Here là liên kết tới tài liệu Doxygen cho lớp học, từ đó bạn có thể tìm thấy tệp tiêu đề khai báo nếu cần. Vì LLVM không cung cấp toán tử < < để truyền các đối tượng StringRef tới luồng std (chúng sử dụng lớp luồng tùy chỉnh nhẹ), tôi đã viết một.
Tuy nhiên, khi tôi sử dụng đặc điểm nó không hoạt động nếu điều hành tùy chỉnh của tôi < < được khai báo sau các đặc điểm (điều này xảy ra bởi vì tôi có các đặc điểm trong một header và các nhà điều hành < < chức năng trong một số khác) . Tôi đã từng nghĩ rằng việc tra cứu trong các mẫu instantiations làm việc từ quan điểm của điểm instantiation, vì vậy tôi nghĩ rằng nó sẽ làm việc. Trên thực tế, như bạn có thể thấy bên dưới, với một lớp khác và toán tử tùy chỉnh < <, được khai báo sau đặc điểm, mọi thứ hoạt động như mong đợi (đó là lý do tại sao tôi mới phát hiện vấn đề này), vì vậy tôi không thể tìm ra điều gì khiến StringRef đặc biệt.
Đây là ví dụ hoàn chỉnh:
#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;
}
Trái với mong đợi của tôi, bản in này:
false
true
Nếu tôi chuyển việc kê khai của người điều khiển < < cho StringRef trước việc kê khai đặc điểm , nó in đúng. Vậy tại sao điều kỳ lạ này lại xảy ra và tôi có thể khắc phục vấn đề này như thế nào?
Đặt toán tử của bạn trong cùng một không gian tên làm loại để bật ADL. – Yakk
@Yakk Đó là câu trả lời, vậy tại sao không viết một câu trả lời? – jrok
@jrok bởi vì tôi đang đặt em bé ngủ một giấc ngủ ngắn, và đó không phải là lạm dụng để kiểm tra nó là vấn đề thực sự và quá trình xây dựng, vv :) – Yakk