1

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?

dabadaba
  • 9,064
  • 21
  • 85
  • 155
  • Does the class `Letters` overload operator << ? – yizzlez Sep 11 '14 at 14:28
  • @awesomeyi oh yeah I forgot to post it – dabadaba Sep 11 '14 at 14:29
  • What of ```<<(std::ostream& os, const Letter& l)``` – Carl Sep 11 '14 at 14:35
  • Either forward declare the operator before `RandomNumberGenerator` or define `generate` after the operator's definition. – David G Sep 11 '14 at 14:38
  • @0x499602D2 now that worked! thanks! could you be so kind to explain the reason why this happens and why this is the solution in an answer? – dabadaba Sep 11 '14 at 14:39
  • @dabadaba C++ expects everything you use to be already defined or at least 'known'. You can often think of the parser reading your source files from top to bottom and thus declaring/defining or forward declaring stuff before using them. – Marco A. Sep 11 '14 at 14:44

1 Answers1

2

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;
Community
  • 1
  • 1
Marco A.
  • 43,032
  • 26
  • 132
  • 246