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

后端 未结 4 1422
礼貌的吻别
礼貌的吻别 2021-01-03 03:33

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

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


        
相关标签:
4条回答
  • 2021-01-03 03:48

    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;
    }
    
    0 讨论(0)
  • 2021-01-03 03:55

    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

    0 讨论(0)
  • 2021-01-03 03:58

    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 ;
    }
    
    0 讨论(0)
  • 2021-01-03 03:58

    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.

    0 讨论(0)
提交回复
热议问题