【问题标题】:Can't use overloaded operator<< to print object's value不能使用重载的 operator<< 来打印对象的值
【发布时间】:2014-11-22 10:32:30
【问题描述】:

我写了元组实现,似乎可行:

template<typename T, typename... U>
struct tuple{
    T first;
    tuple<U...> second;
    tuple()=default;
    tuple(T t, U... u):first(t), second(u...){}
    std::ostream& print(std::ostream& stream){
        stream<<first<<", ";
        return second.print(stream); //not using << to avoid extra () in output
    }
};

template<typename T>
struct tuple<T>{
    T first;
    tuple()=default;
    tuple(T t):first(t){}
    operator T&(){
        return first;
    }
    std::ostream& print(std::ostream& stream){
        return stream<<first;
    }
};

template<typename... T>
inline auto mk_tuple(T... t){
    return tuple<T...>(t...);
}

我以这种方式重载了operator&lt;&lt;

template<typename... T>
std::ostream& operator<<(std::ostream &stream, tuple<T...> &out){
    stream<<'(';
    return out.print(stream)<<')';
}

当我尝试以这种方式使用它时:std::cout&lt;&lt;mk_tuple(1, 2, 3, "xyz", 'c'); 我明白了

error: cannot bind ‘std::ostream {aka std::basic_ostream&lt;char&gt;}’ lvalue to ‘std::basic_ostream&lt;char&gt;&amp;&amp;’

但是,mk_tuple(1, 2, 3, "xyz", 'c').print(std::cout) 有效。
(但不能令人满意,因为它在 C++ 中的语法并不明显)。

在这种情况下我应该如何重载operator&lt;&lt; 才能正确使用它?

【问题讨论】:

    标签: c++ templates c++11 operator-overloading iostream


    【解决方案1】:

    签名错误,你需要:

    template<typename... T>
    std::ostream& operator<<(std::ostream &stream, const tuple<T...> &out){
    //                                             ^^^^^
    

    因为您不会修改输出时的tuple。这样就可以使用常量或临时值调用您的运算符。

    还需要你将print方法标记为const

    std::ostream& print(std::ostream& stream) const {
    //                                        ^^^^^
    

    一般来说,谷歌“const 正确性”并了解 C++ 中的这一基本范式。


    编辑:知道了!试试这个签名:

    template<typename T, typename... U>
    std::ostream& operator<<(std::ostream &stream, const tuple<T, U...> &out){
        stream<<'(';
        return out.print(stream)<<")";
    }
    

    因为一些旧版本的 GCC 似乎有一个错误,阻止他们正确推断 T...s。

    【讨论】:

    • @GingerPlusPlus 我看不懂你的想法,所以你必须更具体:修复print的运算符和both签名后,究竟是什么错误你明白了吗?
    • error: cannot bind ‘std::ostream {aka std::basic_ostream&lt;char&gt;}’ lvalue to ‘std::basic_ostream&lt;char&gt;&amp;&amp;’/usr/include/c++/4.8/ostream:602:5: error: initializing argument 1 of ‘std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::operator&lt;&lt;(std::basic_ostream&lt;_CharT, _Traits&gt;&amp;&amp;, const _Tp&amp;) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; _Tp = tuple&lt;int, int, int, const char*, char&gt;]’ My whole code in online compiler
    • @GingerPlusPlus 呵呵。我的本地系统上的 GCC 4.9 和 GCC 4.8 都接受该确切代码。
    • @GingerPlusPlus Works here 我看不出代码有什么问题。奇怪。
    • @hvd:我有 g++ 4.8.2,在 Rextester 上是 g++ 4.8.1,在它们两个下都不起作用...
    猜你喜欢
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    相关资源
    最近更新 更多