std::vector 的流运算符的参数相关查找
Argument dependent lookup with stream operator for std::vector
我在我的命名空间中为 std::vector
创建了一个流输出运算符,我能够在我以前的调试代码中使用它:
namespace my_company {
template <typename T>
std::ostream &operator<<(std::ostream &os, std::vector<T> const &vec) {
os << "{";
for (int i = 0; i < vec.size(); ++i) {
if (i != 0) {
os << ", ";
}
os << vec[i];
}
os << "}";
return os;
}
template <typename T>
void debug_impl(T const &var, char const *const expr, char const *const file, int const line) {
using std::vector;
std::lock_guard lg(debug_print_mutex);
std::cout << "DEBUG " << file << ":" << line << " T" << std::this_thread::get_id() << "\n " << expr << ": "
<< var << std::endl;}
#define DEBUG(var) ::my_company::debug_impl(var, #var, __FILE__, __LINE__)
}
但现在我想使用我的记录器class:
namespace my_company {
class Logger {
public:
virtual ~Logger() = default;
virtual void log_impl(LogLevel log_level, std::string message) = 0;
template <typename... T>
void log_bits(LogLevel log_level, T const &...ts) {
if (log_level >= threshold)
log_impl(log_level, format_bits(ts...));
}
template <typename... T>
void trace(T const &...ts) {
log_bits(LogLevel::trace, ts...);
}
private:
LogLevel threshold = LogLevel::trace;
};
}
格式化函数是这个:
namespace my_company {
template <typename... T>
std::string format_bits(T const &...ts) {
std::ostringstream oss;
// The following is a C++17 [fold expression](https://en.cppreference.com/w/cpp/language/fold).
(oss << ... << ts);
return oss.str();
}
}
在 debug_impl
函数中,我现在只委托给记录器:
namespace my_company {
template <typename T>
void debug_impl(T const &var, char const *const expr, char const *const file, int const line) {
logger->template trace(file, ":", line, " T", std::this_thread::get_id(), "\n ", expr, ": ", var);
}
}
Clang 不喜欢这样:
logger.h:29:11: error: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
(oss << ... << ts);
^
logger.h:44:27: note: in instantiation of function template specialization 'my_company::format_bits<const char *, char [2], int, char [3], std::thread::id, char [4], const char *, char [3], std::vector<bool, std::allocator<bool>>>' requested here
log_impl(log_level, format_bits(ts...));
^
logger.h:69:5: note: in instantiation of function template specialization 'my_company::Logger::log_bits<const char *, char [2], int, char [3], std::thread::id, char [4], const char *, char [3], std::vector<bool, std::allocator<bool>>>' requested here
log_bits(LogLevel::trace, ts...);
^
util.h:693:20: note: in instantiation of function template specialization 'my_company::Logger::trace<const char *, char [2], int, char [3], std::thread::id, char [4], const char *, char [3], std::vector<bool, std::allocator<bool>>>' requested here
logger->template trace(file, ":", line, " T", std::this_thread::get_id(), "\n ", expr, ": ", var);
^
rotating_buffer.h:40:5: note: in instantiation of function template specialization 'my_company::debug_impl<std::vector<bool, std::allocator<bool>>>' requested here
DEBUG(used);
^
util.h:699:42: note: expanded from macro 'DEBUG'
#define DEBUG(var) ::my_company::debug_impl(var, #var, __FILE__, __LINE__)
^
logger.h:13:15: note: 'operator<<' should be declared prior to the call site
std::ostream &operator<<(std::ostream &os, std::vector<T> const &vec) {
^
我已经在call site之前声明了,都是在logger.h
文件里声明的,其他的都包含进去了。 operator<<
是该文件中的第一件事,因此它应该可用。我认为额外的模板层并没有使它变得更容易。
我已经阅读了其他一些问题,但我不明白如何解决这个问题,因为不允许将 operator<<
放入 std
,但它不起作用在 my_company
中并将其放入全局命名空间也不起作用。我能做什么?
我们在 Linux.
上使用 Clang 11 和 C++20
有些相关:
- Argument Dependent Lookup and stream operators overloading
- Output stream operator Argument Dependent Lookup (ADL) for fundamental/STL types/classes
这似乎是一个 clang 11 错误。
Clang 12 接受代码 Demo。
作为解决方法,您可以使用 (oss << ... << ts);
:
((oss << ts), ...);
我在我的命名空间中为 std::vector
创建了一个流输出运算符,我能够在我以前的调试代码中使用它:
namespace my_company {
template <typename T>
std::ostream &operator<<(std::ostream &os, std::vector<T> const &vec) {
os << "{";
for (int i = 0; i < vec.size(); ++i) {
if (i != 0) {
os << ", ";
}
os << vec[i];
}
os << "}";
return os;
}
template <typename T>
void debug_impl(T const &var, char const *const expr, char const *const file, int const line) {
using std::vector;
std::lock_guard lg(debug_print_mutex);
std::cout << "DEBUG " << file << ":" << line << " T" << std::this_thread::get_id() << "\n " << expr << ": "
<< var << std::endl;}
#define DEBUG(var) ::my_company::debug_impl(var, #var, __FILE__, __LINE__)
}
但现在我想使用我的记录器class:
namespace my_company {
class Logger {
public:
virtual ~Logger() = default;
virtual void log_impl(LogLevel log_level, std::string message) = 0;
template <typename... T>
void log_bits(LogLevel log_level, T const &...ts) {
if (log_level >= threshold)
log_impl(log_level, format_bits(ts...));
}
template <typename... T>
void trace(T const &...ts) {
log_bits(LogLevel::trace, ts...);
}
private:
LogLevel threshold = LogLevel::trace;
};
}
格式化函数是这个:
namespace my_company {
template <typename... T>
std::string format_bits(T const &...ts) {
std::ostringstream oss;
// The following is a C++17 [fold expression](https://en.cppreference.com/w/cpp/language/fold).
(oss << ... << ts);
return oss.str();
}
}
在 debug_impl
函数中,我现在只委托给记录器:
namespace my_company {
template <typename T>
void debug_impl(T const &var, char const *const expr, char const *const file, int const line) {
logger->template trace(file, ":", line, " T", std::this_thread::get_id(), "\n ", expr, ": ", var);
}
}
Clang 不喜欢这样:
logger.h:29:11: error: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
(oss << ... << ts);
^
logger.h:44:27: note: in instantiation of function template specialization 'my_company::format_bits<const char *, char [2], int, char [3], std::thread::id, char [4], const char *, char [3], std::vector<bool, std::allocator<bool>>>' requested here
log_impl(log_level, format_bits(ts...));
^
logger.h:69:5: note: in instantiation of function template specialization 'my_company::Logger::log_bits<const char *, char [2], int, char [3], std::thread::id, char [4], const char *, char [3], std::vector<bool, std::allocator<bool>>>' requested here
log_bits(LogLevel::trace, ts...);
^
util.h:693:20: note: in instantiation of function template specialization 'my_company::Logger::trace<const char *, char [2], int, char [3], std::thread::id, char [4], const char *, char [3], std::vector<bool, std::allocator<bool>>>' requested here
logger->template trace(file, ":", line, " T", std::this_thread::get_id(), "\n ", expr, ": ", var);
^
rotating_buffer.h:40:5: note: in instantiation of function template specialization 'my_company::debug_impl<std::vector<bool, std::allocator<bool>>>' requested here
DEBUG(used);
^
util.h:699:42: note: expanded from macro 'DEBUG'
#define DEBUG(var) ::my_company::debug_impl(var, #var, __FILE__, __LINE__)
^
logger.h:13:15: note: 'operator<<' should be declared prior to the call site
std::ostream &operator<<(std::ostream &os, std::vector<T> const &vec) {
^
我已经在call site之前声明了,都是在logger.h
文件里声明的,其他的都包含进去了。 operator<<
是该文件中的第一件事,因此它应该可用。我认为额外的模板层并没有使它变得更容易。
我已经阅读了其他一些问题,但我不明白如何解决这个问题,因为不允许将 operator<<
放入 std
,但它不起作用在 my_company
中并将其放入全局命名空间也不起作用。我能做什么?
我们在 Linux.
上使用 Clang 11 和 C++20有些相关:
- Argument Dependent Lookup and stream operators overloading
- Output stream operator Argument Dependent Lookup (ADL) for fundamental/STL types/classes
这似乎是一个 clang 11 错误。
Clang 12 接受代码 Demo。
作为解决方法,您可以使用 (oss << ... << ts);
:
((oss << ts), ...);