Home arrow C++ arrow Page 4 - Custom Stream Manipulation in C++
C++

Custom Stream Manipulation in C++


The creators of the STL library have surely gone beyond the expectations of many programmers. However, as perfect and complete as their library may seem at first, you will slowly discover that even they could not cover everything. That's when it is time for you to learn how to create a custom class/function that suits your specific needs.

Author Info:
By: Gabor Bernat
Rating: 5 stars5 stars5 stars5 stars5 stars / 4
May 05, 2009
TABLE OF CONTENTS:
  1. · Custom Stream Manipulation in C++
  2. · Manipulators with No Argument
  3. · Solution for Multiple Arguments
  4. · Templates on the Fly

print this article
SEARCH DEVARTICLES

Custom Stream Manipulation in C++ - Templates on the Fly
(Page 4 of 4 )

Now it is obvious that writing a manipulator for more and more parameters, or more manipulators at the same time, is time consuming and an awkward job. Unless you are certain that you will benefit a great deal, you may hesitate to do it. Whenever you get into a situation where you may need to write many manipulators, writing a good template for what to build later on is a good idea.

As I have just shown you how to write a manipulator for a single argument, I will write the template for two arguments. Note that this will only work if you pass on two arguments. For more arguments, extend the template list; for less, just remove it from the template list, and with it any code related to that variable.

On the other hand, you can also create a custom struct and group more data inside of it, but here it goes:


#include <iostream>

#include <string>


using namespace std;


// the template class that will do the job in the background

template<typename A1, typename A2, typename BT>

class TwoArgManip

{

public:

 

// take the arguments and the pointer to the function

TwoArgManip (basic_ostream<BT>&

(*pFun) (basic_ostream<BT>&, A1, A2), A1 val, A2 val2)

// initialize using the : method

: manipFun_(pFun), val_1(val), val_2(val2) {}

 

// the operator overload

void operator( )(basic_ostream<BT>& os) const

{// Invoke the function pointer with the

// stream and value

manipFun_(os, val_1,val_2);

}

private:

A1 val_1;

A2 val_2;

// this will hold the reference to the function

basic_ostream<BT>& (*manipFun_)

(basic_ostream<BT>&, A1, A2);

};


// a template for the operator overload

template<typename A1, typename A2, typename BT>

basic_ostream<BT>& operator<<

(basic_ostream<BT>& stream,

const TwoArgManip<A1,A2,BT>& manipulator)

{

manipulator(stream);

return(stream);

}


Here you should note that we also save a function reference during the initialization, so later on we can call the function inside the operator() overload. The compiler will automatically note that, upon run time, the operator<< will be used, so that will be constructed by default.

Additionally, you may say that I promised one with two arguments, but it turned out to be one with three. How is this possible? Well, you see, the third parameter is for the Base Type, or more commonly, whether we are talking about a stream constructed on the wide or narrow character.

Here is how you use the class by declaring two simple functions rather than two functions and a class:



// The function that will be called by the manipulator

// Here you add any modification that you do for the stream

ostream& setWidthAndFillFunc(ostream& stream, int n, char c) {

stream.width(n);

stream.fill(c);

return(stream);

}


// The manipulator used by the coder

TwoArgManip<int, char,char> setWidthAndFill(int n, char a) {

return

(TwoArgManip<int,char,char>(setWidthAndFillFunc, n,a));

}


In addition, using it is just as simple:



cout << setWidthAndFill(10, '@') << right << "Yetin";


With the output:


@@@@@Yeti

Press any key to continue . . .


That is all you need to know, folks! By now, you have mastered the manipulators for streams at a level close to perfection. Thank you for reading through my article. As usual, I invite you to offer your questions and comments related to this article here at the blog or over at DevHardware Forums. Live with Passion!


DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

blog comments powered by Disqus
C++ ARTICLES

- Intel Threading Building Blocks
- Threading Building Blocks with C++
- Video Memory Programming in Text Mode
- More Tricks to Gain Speed in Programming Con...
- Easy and Efficient Programming for Contests
- Preparing For Programming Contests
- Programming Contests: Why Bother?
- Polymorphism in C++
- Overview of Virtual Functions
- Inheritance in C++
- Extending the Basic Streams in C++
- Using Stringstreams in C++
- Custom Stream Manipulation in C++
- General Stream Manipulation in C++
- Serialize Your Class into Streams in C++

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials