简体   繁体   English

运算符<<在构造函数中重载

[英]operator << overloading in a constructor

I'm debugging a program and I would like to make printing from that pattern: 我正在调试程序,我想从该模式进行打印:

 std::cout << firstVar << ", " << secondVar << ", " << thirdVar << endl ;

shorter, ie, the same thing should happen if we will write the code: 更短,也就是说,如果我们编写代码,则应该发生相同的事情:

shortPrint(std::cout) << firstVar << secondVar << thirdVar;

note: there is no limit for the variables quantity, it can be 1 and it can be 20, so that should also work: 注意:变量数量没有限制,可以为1,也可以为20,因此也可以使用:

shortPrint(std::cout) << firstVar << secondVar << thirdVar << anotherVar << oneMoreVar;

Someone told me that the easiest wat to do that is to create class that is called "shortPrint". 有人告诉我,最简单的方法就是创建一个称为“ shortPrint”的类。

Can anyone help me figuring this out? 谁能帮我解决这个问题?

For start, I would say that I only need to implement a constructor and operator << overloading, but I'm not sure how to do that exactly in that case. 首先,我会说我只需要实现一个构造函数和一个运算符<<重载,但是我不确定在那种情况下该怎么做。

Yes create a shortPrint class with an appropriate overloaded operator. 是的,使用适当的重载运算符创建shortPrint类。 Something like this : 像这样的东西:

class shortPrint {
  ostream &o;
public:
  shortPrint(ostream &o) : o(o) {}
  template <typename T> shortPrint &operator<<(const T &t) {
    o << t << ',';
    return *this;
  }
  // support for endl, which is not a value but a function (stream->stream)
  shortPrint &operator<<(ostream& (*pf)(std::ostream&)) {
    o << pf;
    return *this;
 }
};

That should work (basically). 这应该工作(基本上)。

To eliminate the problem of extra commas use this : 为了消除多余的逗号问题,请使用以下命令:

class shortPrint {
  class shortPrint2{
    shortPrint &s;
  public:
    shortPrint2(shortPrint &s) : s(s) {}
    template <typename T> shortPrint2 &operator<<(const T &t) {
      s.o << ',' << t ;
      return *this;
    }
    shortPrint &operator<<(ostream& (*pf)(std::ostream&)) {
      s.o << pf;
      return s;
    }
  };
  ostream &o;
  shortPrint2 s2;
public:
  shortPrint(ostream &o) : o(o), s2(*this) {}
  template <typename T> shortPrint2 &operator<<(const T &t) {
    o << t;
    return s2;
  }
  shortPrint &operator<<(ostream& (*pf)(std::ostream&)) {
    o << pf;
    return *this;
  }
};

You can do something like the following: 您可以执行以下操作:

class _ostream_wrap
{
public:
    template <class T>
    _ostream_wrap& operator << (const T & v)
    {
        m_ost << "[ " << v << " ]";
        return (*this);
    }
    explicit _ostream_wrap(std::ostream & ost)
        :m_ost(ost)
    {}
private:
    std::ostream&   m_ost;
};

template <class OSTREAM>
_ostream_wrap shortPrint(OSTREAM & o)
{
    return _ostream_wrap(o);
}

//...
shortPrint(std::cout) << 1 << 2;

however this implementation will not work on rvalues: 但是,此实现不适用于右值:

//you can't do something like the following:
shortPrint(MyOstream(some_args)) << 1;

This is because the class _ostream_wrap keeps a reference to the stream and for rvalues case it needs to make a copy. 这是因为类_ostream_wrap保留_ostream_wrap的引用,对于右值,它需要进行复制。 To make a copy you need to have two implementations (this would be the final version): 要制作副本,您需要两个实现(这将是最终版本):

template <class OSTREAM>
class _ostream_wrap
{
public:
    template <class T>
    _ostream_wrap<OSTREAM>& operator << (const T & v)
    {
        m_ost << "[ " << v << " ]";
        return (*this);
    }


public:
    //the constructor is harder to write so i decided 
    //that for this i will keep the member public
    OSTREAM     m_ost;
};

template <class OSTREAM>
_ostream_wrap<OSTREAM&> shortPrint(OSTREAM & o)
{
    _ostream_wrap<OSTREAM&> rvalue;
    rvalue.m_ost = o;
    return rvalue;
}
template <class OSTREAM>
_ostream_wrap<OSTREAM> shortPrint(const OSTREAM & o)
{
    _ostream_wrap<OSTREAM> rvalue;
    rvalue.m_ost = o;
    return rvalue;
}

Here's something with very basic functionality: 这里有一些非常基本的功能:

#include <iostream>

struct shortPrint {
    explicit shortPrint(std::ostream& os)
        : strm(&os), first(true) {}

    template<typename T>
    shortPrint& operator<<(T&& t)
    {
        if (first) {
            first = false;
        } else {
            *strm << ", ";
        }
        *strm << std::forward<T>(t);
        return *this;
    }

    shortPrint& operator<<( std::ostream& (*func)(std::ostream&) )
    {
        *strm << func;
        return *this;
    }

private:

    std::ostream* strm;
    bool first;
};

int main()
{
    int i = 3;
    shortPrint(std::cout) << "1" << 2 << i << std::endl;
    shortPrint(std::cout) << 4;
}

The tricky part is getting the commas to be printed correctly. 棘手的部分是使逗号正确打印。 I chose to print them before every streamed object, except before the very first one. 我选择每个流对象之前打印它们,除了第一个对象之前。 As you can see, there's one general operator<< template that simply prints the comma and forwards the argument. 如您所见,有一个通用operator<<模板,它简单地打印逗号并转发参数。 The next problem are stream manipulators, because we don't want to print commas before them. 下一个问题是流操纵器,因为我们不想在它们之前打印逗号。 The other operator<< overload takes care of that. 另一个operator<<重载可以解决这个问题。 If you want to be more generic, there's two more you need to take care of (see no. 9 here ). 如果您想更通用一些,还需要处理两个(请参见此处的第 9号)。

Hope that helps. 希望能有所帮助。

Return the ostream from the function. 从函数返回ostream。 Something like: 就像是:

std::ostream &shortPrint(std::ostream &out) {
    //whatever you need here
    return out;
}

Edit: you the kind of formatting you need, you need to make a class with overloaded stream operator that returns the class. 编辑:您需要的格式化类型,您需要使用返回该类的重载流运算符来创建一个类。 But you need to keep the reference to the needed stream in the class. 但是您需要在类中保留对所需流的引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM