0

here is my function

ostream margain(std::string firstWord)
{
    ostream x;
    x << std::setw(20) << firstWord;
    return x;
}

in main I want to use the function as follow

std::cout<< margain("start") << "````````````````````````````````````" << std::endl;
// print things out
//then
std::cout<< margain("End") << "````````````````````````````````````" << std::endl;

I get the output, start or end is not shown, and the return value is

0````````````````````````````````````

how can I fix it? and why?

Edit: I know that the function is what causing that, because if I add this

cout << std::setw(20) << firstWord; in the function, It prints right,

I fixed it, not the best way, but as

calling the function as

margain(std::cout, "End") << "~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~" << endl;

the function looks like

ostream& margain(ostream& stream, std::string firstWord)
{
    stream << std::left << std::setw(10) << firstWord;
    return stream;
}

anyone know better way?

aah134
  • 860
  • 12
  • 25
  • when you declare x in margain, is there a compiler error happen when you do that? as I do it this moment I was told that error on 'std::basic_ostream<_Elem,_Traits>' because no appropriate default constructor available. – DarkHorse Sep 05 '13 at 14:36

2 Answers2

2

You are printing the value of the ostream, not value of firstword. The ostream x in this case is an unopened stream, so it doesn't "do" anything. Because the compiler allows to conversion to either bool (C++11) or void * (before C++11), the "value" from that conversion is printed. Note that any operations on x will not affect cout.

The easiest solution, I would think is to actually add std::setw(20) to your output line:

std::cout<< std::setw(20 << "End" << "````````````````````````````````````" << std::endl;

The other choice would be to pass the std::cout to margain, and return the std::string, something like this:

std::string margain(ostream& x, const std::string& firstWord)
{
    x << std::setw(20);
    return firstWord;
}

then you could do:

std::cout<< margain(cout, "start") << "````````````````````````````````````" << std::endl;

But it's not exactly flexible or "neat".

The third option is of course to have a MarginString class:

class MarignString
{
  private:
     int margin;
     std::string str;
  public:
     MarginString(int margin, std::string str) margin(margin), str(str) {}
     operator std::string() { return str; }
     friend std::ostream& operator(std::ostream& os, const MarginString& ms);
 };


 std::ostream& operator(std::ostream& os, const MarginString& ms)
 {
     os << std::setw(ms.margin) << ms.str;
     return os;
 }

 ...
 std::cout<< MarginString(20, "start") << "````````````````````````````````````" << std::endl;

Note that this last way is probably not that great either... ;)

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
1
struct margin
{
    margin(std::string word) : word(word) { }

    friend std::ostream& operator <<(std::ostream& os, margin const& m)
    {
         return os << std::setw(20) << m.word;
    }

private:
    std::string word;
};
David G
  • 94,763
  • 41
  • 167
  • 253
  • I think the `operator<<` function needs to go outside the `struct` (or be a non-friend but static function) – Mats Petersson Sep 05 '13 at 14:36
  • It may well compile, but the first argument to `operator <<` should be the `ostream`, and in your case, it will be a `this`, right? Or does sticking `friend` on the front of a function have a similar effect to static, that it's no longer a member function? – Mats Petersson Sep 05 '13 at 15:32