因为我正在使用mikrocontroller,我没有std :: cout,我想为我的印刷类定义几个operator<<()
函数。
因为我有几个打印后端类(每个输出通道一个,例如uart,wireless,aso。),我想将我的operator<<()
函数定义为模板。
但如果我想称这种超载,他们就不会工作。我遇到像
这样的编译器错误no match for ‘operator<<’ (operand types are ‘print_t’ and ‘gsl::basic_string_span<const char, -1>’)
我有以下示例:
#include <gsl/string_span>
template <typename T=char, std::size_t N>
constexpr gsl::cstring_span<> gen_cstring_span(const char (&a)[N]) noexcept {
return gsl::cstring_span<>(a, N);
}
class print_t {
public:
inline void append(const gsl::cstring_span<> buf) noexcept {
for(auto c : buf) {
printf("%c", c);
}
}
};
print_t p;
class prefix_t {
public:
static constexpr char prefix[] = "Prefix: ";
template<typename T>
print_t& operator<<(T&& arg) noexcept {
fprintf(stderr, "fwd, ");
p.append(prefix);
p << std::forward<T>(arg);
return p;
}
};
template<typename T>
using span_append_function_exists = std::is_member_function_pointer<decltype(static_cast<void(T::*)(const gsl::cstring_span<>)noexcept>(&T::append))>;
template<typename stream_t, std::enable_if_t<
span_append_function_exists<stream_t>::value, bool>>
stream_t& operator<<(stream_t& sb, const gsl::cstring_span<> str) noexcept {
sb.append(str);
fprintf(stderr, "cstring_span, ");
return sb;
}
template<typename stream_t, typename T=char, std::size_t N>
stream_t& operator<<(stream_t& sb, const char (&str)[N]) noexcept {
fprintf(stderr, "string_literal, ");
auto s = gen_cstring_span(str);
return sb << s;
}
template<typename stream_t>
stream_t& operator<<(stream_t& sb, const bool flag) noexcept {
fprintf(stderr, "bool, ");
if(flag) {
return sb << gen_cstring_span("true");
} else {
return sb << gen_cstring_span("false");
}
}
prefix_t pre;
int main() {
gsl::cstring_span<> span{gen_cstring_span("span")};
p << span << "\n";fprintf(stderr, "\n");
p << "string-literal" << "\n";fprintf(stderr, "\n");
p << true << "\n";fprintf(stderr, "\n");
pre << span << "\n";fprintf(stderr, "\n");
pre << "string-literal" << "\n";fprintf(stderr, "\n");
pre << true << "\n";fprintf(stderr, "\n");
}
这个例子应该是C ++ 17(并且设计用于经典的PC,但它应该移植到MC。)在这个例子中,print-backend-class将是print_t
每个operator<<()
函数都有一个模板参数stream_t
,在此示例中应该成为后端类print_t
。
我曾与std::enable_if<>
合作,仅在定义了append()函数的类上启用sream_t
参数,但我没有成功。
此外,如果我在类prefix_t
上应用运算符,它应该将所有内容打印到后端,并在输出之前另外添加前缀值。
预期的STDOUT:
span
string-literal
true
Prefix: span
Prefix: string-literal
Prefix: true
预期的STDERR:
cstring_span,
string_literal, cstring_span,
bool, cstring_span,
fwd, cstring_span,
fwd, string_literal, cstring_span,
fwd, bool, cstring_span,
编译器错误的一小部分:
tmp3.cpp: In function ‘int main()’:
tmp3.cpp:65:7: error: no match for ‘operator<<’ (operand types are ‘print_t’ and ‘gsl::cstring_span<> {aka gsl::basic_string_span<const char, -1>}’)
p << span << "\n";fprintf(stderr, "\n");
~~^~~~~~~
tmp3.cpp:36:11: note: candidate: template<class stream_t, typename std::enable_if<std::is_member_function_pointer<decltype (static_cast<void (T::*)(gsl::basic_string_span<const char, -1>) noexcept>(& T:: append))>::value, bool>::type <anonymous> > stream_t& operator<<(stream_t&, gsl::cstring_span<>)
stream_t& operator<<(stream_t& sb, const gsl::cstring_span<> str) noexcept {
^~~~~~~~
tmp3.cpp:36:11: note: template argument deduction/substitution failed:
tmp3.cpp:65:10: note: couldn't deduce template parameter ‘<anonymous>’
p << span << "\n";fprintf(stderr, "\n");
^~~~
tmp3.cpp:43:11: note: candidate: template<class stream_t, class T, long unsigned int N> stream_t& operator<<(stream_t&, const char (&)[N])
stream_t& operator<<(stream_t& sb, const char (&str)[N]) noexcept {
^~~~~~~~
tmp3.cpp:43:11: note: template argument deduction/substitution failed:
tmp3.cpp:65:10: note: mismatched types ‘const char [N]’ and ‘gsl::cstring_span<> {aka gsl::basic_string_span<const char, -1>}’
p << span << "\n";fprintf(stderr, "\n");
^~~~
tmp3.cpp:50:11: note: candidate: template<class stream_t> stream_t& operator<<(stream_t&, bool)
stream_t& operator<<(stream_t& sb, const bool flag) noexcept {
^~~~~~~~
tmp3.cpp:50:11: note: template argument deduction/substitution failed:
tmp3.cpp:65:10: note: cannot convert ‘span’ (type ‘gsl::cstring_span<> {aka gsl::basic_string_span<const char, -1>}’) to type ‘bool’
p << span << "\n";fprintf(stderr, "\n");
我正在使用带有g ++ 7.3的C ++ 17。