0

I have a method to log with the following definition:

void log(std::string s) {
    std::string tag = "main";
    std::cout << tag << " :" << s << std::endl;
}

I'm trying to call this method like this:

log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));

direction and count are integers.

I'm getting this following error with << underlined in red:

no operator << matches these operands. operand types are const char [10] << std::string

I have #include<string> in my header to make sure my strings are working as they should.

I tried std::string("direction") and still the issue was same.

Beginner in C++. Help would be appreciated.

2
  • std::string("direction") + std::to_string(direction) ... What you're trying to concatinate is a char array and a string; not 2 strings Commented Sep 21, 2017 at 9:25
  • This was not required: "direction" + std::to_string(direction) worked. Commented Sep 21, 2017 at 9:39

5 Answers 5

2

operator<< isn't used for arbitrary string concatenation - it is called an "output stream operator", and it is only used in the context of std::ostream.

When you say...

std::cout << tag << " :" << s << std::endl;

...you're actually writing code roughly equivalent to:

std::cout.operator<<(tag).operator<<(" :").operator<<(s).operator<<(std::endl);

As you can see operator<< knows how to work with std::cout and std::string, but not between strings.


In order to concatenate std::string instances, you can simply use operator+:

log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));

Please note that this concatenation technique is not the most efficient: you might want to look into std::stringstream or simply use std::string::reserve to avoid unnecessary memory allocations.

Sign up to request clarification or add additional context in comments.

2 Comments

Okay. But I just changed << to + and I don't see that error anymore. Conversion still necessary?
@FaizuddinMohammed: yeah sorry, you don't actually need to convert "direction" to an std::string explicitly as operator+ is defined for (const char*, const std::string&).
2

Substitute the << with the + operator as you are manipulating the string, not the stream:

log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));

Comments

0

If you're determined to use the operator<< notation you need an object that understands it.

Here's such an object (I make no claims that this is a good idea):

#include <string>
#include <sstream>
#include <iostream>

void log(std::string s) {
    std::string tag = "main";
    std::cout << tag << " :" << s << std::endl;
}

struct string_accumulator
{
    std::ostringstream ss;

    template<class T>
    friend string_accumulator& operator<<(string_accumulator& sa, T const& value)
    {
        sa.ss << value;
        return sa;
    }

    template<class T>
    friend string_accumulator& operator<<(string_accumulator&& sa, T const& value)
    {
        return operator<<(sa, value);
    }

    operator std::string () { return ss.str(); }
};

inline auto collect() -> string_accumulator
{
    return string_accumulator();
}

int main()
{
    int direction = 1;
    int count = 1;
    log(collect() << "direction" << std::to_string(direction) << ", count: " << std::to_string(count));
}

5 Comments

std::ostringstream is such an object and is standard
you could also write a std::string operator << (std::string, std::string) if you don't want to use such an object ... I'm not suggesting it, but you can
@BasileStarynkevitch that's why I used it :)
@UKMonkey apart from the whole "surprising behaviour in the global namespace" argument, you'd have difficulty when it came to io manipulators. This is why I've proxied the ostringstream. It also now by default understands everything in <iomanip>.
@RichardHodges ohh, I'm not at all suggesting that someone implement that operator, but it's just another way of having that syntax :) Even you in your answer said 'I make no claims this is a good idea' so I put another suggestion under the same heading
0

The prototype of your function is void log(std::string s);. It awaits for an std::string. So you need to pass a string to it, not a stream!

So, change this:

log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));

to this:

log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));

where I only changed the << operator to + operator. It will now concatenate everything inside the parentheses to a single std::string.


Your attempt implies that you wanted to pass std::ostream as the parameter. Maybe you want to read C++ Passing ostream as parameter. However, if I were you, I would just overload <<.

1 Comment

Oh. That's definitely helpful. So, if I use std::ostream will it work? Let me test that.
-2

why don't you use: // just include thisusing namespace std;

2 Comments

a) That's terrible advice and b) it doesn't even answer the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.