C ++:operator<<超载无效

时间:2018-04-06 22:11:23

标签: c++ templates c++17

因为我正在使用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。

0 个答案:

没有答案