dabadaba
dabadaba

Reputation: 9522

cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'

There are many questions with this title around StackOverflow with this title but none helped me and I don't really understand what's going on.

I am trying to make a class that generates a random word. First I am trying to put all vowels and consonants in two different static vectors; however when testing the class I get this error:

cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'

I don't really understand this error. ostream rvalue? I have never seen this and I can't think of any situation where that would make sense.

This is my class so far:

class RandomWordGenerator {
    public:
        RandomWordGenerator() {
            vowels.push_back(Letter('A'));
        }
        static Word generate() {
            std::cout << vowels.front() << std::endl; // the error pops here
            Word w(std::string("test"));
            return w;
        }
    private:
        static std::vector<Letter> vowels;
        static std::vector<Letter> consonants;
};

std::ostream& operator <<(std::ostream& os, Letter& l) {
    return os << l.inner(); // a std::string
}

Why is this happening? How can I solve it?

Upvotes: 1

Views: 6440

Answers (1)

Marco A.
Marco A.

Reputation: 43662

First off: declare the function to accept a const Letter&, then define your member static variable and forward declare or define the operator before using it

std::ostream& operator <<(std::ostream& os, const Letter& l);

class RandomWordGenerator {
    public:
        RandomWordGenerator() {
            vowels.push_back(Letter('A'));
        }
        static Word generate() {
            std::cout << vowels.front() << std::endl; // the error pops here
            Word w(std::string("test"));
            return w;
        }
    public:
        static std::vector<Letter> vowels;
        static std::vector<Letter> consonants;
};

std::vector<Letter> RandomWordGenerator::vowels;

std::ostream& operator <<(std::ostream& os, const Letter& l) {
    return os << l.inner(); // a std::string
}

Forward declaring or defining operators and functions before using them is both a good programming practice and usually a mandatory requirement to enforce type safety: the compiler needs to know the types it's dealing with along with the entire signature. For a more thorough explanation I recommend reading this post: https://stackoverflow.com/a/4757718/1938163

Note that you could also declare the function as a friend function but there's a catch here: friend declaration not forward declaring

std::ostream& operator <<(std::ostream& os, const Letter& l) {
    return os << l.inner(); // a std::string
}

class RandomWordGenerator {
    public:
        RandomWordGenerator() {
            vowels.push_back(Letter('A'));
        }

        friend std::ostream& operator <<(std::ostream& os, const Letter& l);

        static Word generate() {
            std::cout << vowels.front() << std::endl; // the error pops here
            Word w(std::string("test"));
            return w;
        }


    public:
        static std::vector<Letter> vowels;
        static std::vector<Letter> consonants;
};

std::vector<Letter> RandomWordGenerator::vowels;

Upvotes: 2

Related Questions