How to write a function wrapper for cout that allows for expressive syntax?

。_饼干妹妹 提交于 2019-12-18 17:12:52

问题


I'd like to wrap std::cout for formatting, like so:

mycout([what type?] x, [optional args]) {
    ... // do some formatting on x first
    std::cout << x;
}

and still be able to use expressive syntax like

mycout("test" << i << endl << somevar, indent)

instead of being forced to be more verbose like

mycout(std::stringstream("test") << i ...)

How can I implement this? What type to make x?

Edit: added consideration for optional arguments


回答1:


How about this:

struct MyCout {};

extern MyCout myCout;

template <typename T>
MyCout& operator<< (MyCout &s, const T &x) {
  //format x as you please
  std::cout << x;
  return s;
}

And put MyCout myCout; into any one .cpp file.

You can then use myCout like this:

myCout << "test" << x << std::endl;

And it will call the template operator<< which can do the formatting.

Of course, you can also provide overloads of the operator for special formatting of specific types if you want to.

EDIT

Apparently (thanks to @soon), for standard manipulators to work, a few more overloads are necessary:

MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ostream &)) {
  f(std::cout);
  return s;
}

MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ios &)) {
  f(std::cout);
  return s;
}

MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ios_base &)) {
  f(std::cout);
  return s;
}

EDIT 2

I may have misunderstoor your original requirements slightly. How about this (plus the same manipulator overloads as above):

struct MyCout
{
  std::stringstream s;

  template <typename T>
  MyCout& operator << (const T &x) {
    s << x;
    return *this;
  }

  ~MyCout() {
    somehow_format(s);
    std::cout << s.str();
  }
};

int main() {
  double y = 1.5;
  MyCout() << "test" << y;
}



回答2:


This comes easy with variadic template arguments:

template <class T>
void print(T t)
{
    std::cout << t;
}

template <class T, class... Args>
void print(T t, Args... args)
{
    std::cout << t << std::endl;
    print(args...);
}

int main()
{
    std::cout << std::boolalpha;
    print(3, 's', true, false);
}

Output:

3
s
true
false

Live Demo




回答3:


You can use this kind of class:

#include <iostream>

using namespace std;

class CustomOut
{
public:

    template<class T>
    CustomOut& operator<<(const T& obj)
    {
        cout << " my-cout " << obj;
        return *this;
    }

};

int main()
{
    CustomOut mycout;
    mycout << "test" << 4 << "\n" << 3.4;
}

You'd need more code to use std::endl and other functors, so i've used here simple \n instead.




回答4:


A variation from the answers:

#include <iostream>

using namespace std;

class MyCout 
{
public:
  MyCout& operator()(bool indent) { 
    if ( indent ) cout << '\t'; 
    return *this;
  }

  template<class T>
  MyCout& operator<<(T t) {
    cout << t;
    return *this;
  }

  MyCout& operator<<(ostream& (*f)(ostream& o)) {
    cout << f;
    return *this;
  };
};

int main()
{
  MyCout mycout;
  int x = 10;
  mycout(true)<< "test" << 2 << x << endl ;
}


来源:https://stackoverflow.com/questions/16444119/how-to-write-a-function-wrapper-for-cout-that-allows-for-expressive-syntax

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!