no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and...

Hello:
Does anyone know how to fix the code? It´s a calculator that uses different classes.

Here is what the compiler says when I try to compile:
no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'expression')
cout << "= " << expression(ts) << endl;
^

Here is the main source:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;
#include <string>
#include "token_stream.h";
#include "expression.h";
#include "primary.h";
#include "term.h";
#include "myerror.h";
#include "token.h";


int main() try {
    Token tok{};
    Token_stream ts{};
    while( cin )
    {
    cout << "> "; // Prompt
    tok = ts.get();
    if( tok.kind == 'q' ) break;
    if( tok.kind == ';' ) continue;
    ts.putback( tok );
    cout << "= " << expression(ts) << endl; //I GET THE MISTAKE HERE
    }
    return 0;
}

catch( exception& e ) {

    cerr << e.what();
    return -2;
}

catch(const char* d ) {
    cerr << "Fehler:"<<endl<<d<<endl;
    return -1;
}


Here is the "expression.h" class:

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef EXPRESSION_H
#define EXPRESSION_H
#include "token_stream.h"

class expression
{
public:
    expression(Token_stream& ts );
};

#endif // EXPRESSION_H


and here the expression.cpp part:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "expression.h"
#include "token_stream.h"
#include <iostream>;
#include "term.h"
#include "myerror.h"
#include "token.h"
#include "primary.h"
using namespace std;
#include <string>;
/*
expression::expression()
{
}
*/

double expression::expression( Token_stream& ts ) // "plus" and "minus"
{
    double d1{ term( ts ) };
    Token t1{};
    while( true )
    {
        t1 = ts.get();
        switch( t1.kind )
        {
        case '+': d1 += term( ts );
            break;
        case '-': d1 -= term( ts );
            break;
        default: ts.putback( t1 );
            return d1;
        }
    }
}


Hope you help me I don´t understand what I have done wrong :(
Last edited on
expression::expression is a constructor. Constructors are not allowed to return anything. The way you are using it, it seems that it shouldn't be in a class. Just make it a function on its own and give it a meaningful name.

Alternatively, inititalize the class in a ctor and overload operator().
1
2
3
4
5
6
7
8
9
10
11
12
13
class expression {
    Token_stream &ts;
public:
    expression(Token_stream &ts) : ts(ts) {}
    double operator();
}

double expression::operator() {
    // your code here
}

expression e(ts);
cout << e() << '\n';


Which is better depends on how you are using it.
Last edited on
Here are the other classes:
My error class:
1
2
3
4
5
6
7
8
#ifndef MYERROR_H
#define MYERROR_H
#include <stdexcept>
#include <string>
using std::string;
void error( string s ) { throw std::runtime_error{ s }; }
void error( string s1, string s2 ) { error( s1 + s2 ); }
#endif // MYERROR_H 

primary.h:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef PRIMARY_H
#define PRIMARY_H
#include "token_stream.h"

class primary
{
public:
//    primary();
    primary( Token_stream& ts );
};

#endif // PRIMARY_H 

primary.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "primary.h"
#include "token_stream.h"
#include "expression.h"

/*primary::primary()
{
}
*/
primary::primary( Token_stream& ts ) // Numbers and parenthesis
{
    Token t3{ ts.get( ) };
    switch( t3.kind )
    {
    case '9': return t3.value;
    case '(': {
        double d3{ expression( ts ) };
        if( ts.get().kind != ')' ) error( "no right parenthesis" );
        return d3;
    }
    default: error( "no Primary" );
    }
}

term.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef TERM_H
#define TERM_H
#include "token_stream.h"
#include "primary.h"

class term
{
public:
//    term();
    term( Token_stream& ts );
};

#endif // TERM_H 


term.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "term.h"
#include "primary.h"
/*
term::term()
{

    }
*/
double term::term( Token_stream& ts ) // multiplication and division
    {
        double d2{ primary( ts ) };
        Token t2{};
        while( true )
        {
            t2 = ts.get();
            switch( t2.kind )
            {
            case '*': d2 *= primary( ts );
                break;
            case '/': {
                double divisor{ primary( ts ) };
                if( divisor == 0 ) error( "Division through 0" );
                d2 /= divisor;
                break;
            }
            default: ts.putback( t2 );
                return d2;
            }
        }
    }


token.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef TOKEN_H
#define TOKEN_H
#include <iostream>
using namespace std;
#include <string>


class Token {
public:
    char kind; // Categories of the symbols
    double value; // The value
    void print() const {
        if( kind == '9' ) cout << value;
        else cout << kind;
    }
    // Constructor, create a Token of a char:
    Token( const char& ch ) : kind{ch}, value{0.0} { /*doesn´t do anything */ }

    //Constructor, create a Number-Token of a double:
    Token( const double& val ) : kind{'9'}, value{val} { /* doesn´t do anything */ }

    // Standard constructor, create the standardtoken without specification:
    Token( ) : Token{0.0} { /* doesn´t do anything */ }
};

#endif // TOKEN_H 


token.cpp:
1
2
3
4
5
6
7
8
9
10
#include "token.h"


Token::Token( char ch ) : kind{ ch }, value{ 0.0 }
{}
Token::Token( double val ) : kind{ '9' }, value{ val }
{}
// Standard constructor
Token::Token( ) : Token{0.0}
{}

token_stream.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef TOKEN_STREAM_H
#define TOKEN_STREAM_H
#include "token.h";
#include "myerror.h";

class Token_stream
{
public:
    Token_stream();
    Token get( ); // Create Token of std::cin
    void putback( const Token& t )
    { // Trick: Buffer a Token
        if( full ) error( "void Token_stream::putback(), Buffer full" );
        buffer = t; full = true;
    }
private:
    bool full; // Is a token in Buffer?
    Token buffer; // Trick: Place to buffer a token
};

#endif // TOKEN_STREAM_H 

token_stream.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "token_stream.h"
#include <iostream>
#include "token.h"

using namespace std;

Token_stream::Token_stream()
{

}

Token Token_stream::get( )
{
if( full )
{
    full = false; return buffer;
}
char ch{ }; cin >> ch;
switch( ch ) {
    case ';': // Finalize a calculation
    case 'q': // End of Program
    case '(':
    case ')':
    case '+':
    case '-':
    case '*':
    case '/':
        return Token{ ch }; // every symbol has its own tokens
    case '.':
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9': // numbers as tokens
    {
        cin.putback( ch ); // the cin Stream has also a buffer
        double val{ }; cin >> val;
        return Token{ val };
    }
    default: error( "Token Token_stream::get(), unknown Token" );
}
}


Thank you for your help
Last edited on
Hi tpb:

you said I should try to give it a function of its own with a meaninful name. Here is the problem:
I have 3 functions:
1.- expression. 2.- term. 3.- primary.
All of these functions depend on each other.

We were told we should do the calculator with the given classes "token" and "token_stream", and that we should add the functions in the main part.

When I tried to add the functions, if I put at first the expression function, it needed the term function. When writing the term function, it needed "primary" and when writing primary, it needed "expression".

Someone said one should create classes for each function and then add them in the main part with include, therefore I did them.

Now you say I should do this functions on their own but to be honest, where? I was thinking about creating a class named "functions" and then putting all of them there, but I´m not sure if we are allowed to change the code of the functions or if that´s the only way that exists to make the program run.

Thanks!
So, instead of having the classes "expression", "term" and "primary" I added them in one class called "functions". Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include "token_stream.h"


class functions
{
public:
    functions();
    double expression(Token_stream& ts );
    double term( Token_stream& ts );
    double primary( Token_stream& ts );
};

#endif // FUNCTIONS_H


And here is the functions.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "functions.h"

functions::functions()
{
}

double functions::expression(Token_stream &ts)
{
    double d1{ term( ts ) };
    Token t1{};
    while( true )
    {
        t1 = ts.get();
        switch( t1.kind )
        {
        case '+': d1 += term( ts );
            break;
        case '-': d1 -= term( ts );
            break;
        default: ts.putback( t1 );
            return d1;
        }
    }
}
double functions::term( Token_stream& ts )
{
    double d2{ primary( ts ) };
    Token t2{};
    while( true )
    {
        t2 = ts.get();
        switch( t2.kind )
        {
        case '*': d2 *= primary( ts );
            break;
        case '/': {
            double divisor{ primary( ts ) };
            if( divisor == 0 ) error( "Division durch 0" );
            d2 /= divisor;
            break;
        }
        default: ts.putback( t2 );
            return d2;
        }
    }
}
double functions::primary( Token_stream& ts )
{
    Token t3{ ts.get( ) };
    switch( t3.kind )
    {
    case '9': return t3.value;
    case '(': {
        double d3{ expression( ts ) };
        if( ts.get().kind != ')' ) error( "keine rechte Klammer" );
        return d3;
    }
    default: error( "kein Primary" );
    }
}


I changed the main part as well. I included the "functions.h" header and changed the line:
 
cout << "= " << functions.expression(ts) << endl;

Instead of
 
cout << "= " << expression(ts) << endl;

And now I receive this:
expected primary-expression before '.' token
cout << "= " << functions.expression(ts) << endl;
^
You're problem, as I understand it, is that you have three functions that create a circular dependency. That's easy to deal with. Just put the function prototypes above the functions.
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

// function prototypes
int f(int n);
int g(int n);
int h(int n);

int main() { std::cout << f(1) << '\n'; }

int f(int n) { return n > 3 ? n : g(n); }   // f knows about g because of the prototype
int g(int n) { return h(n+1); }    // g knows about h because of the prototype
int h(int n) { return f(n+1); }    // h would know about f even without the prototype,
                                   // but it's still a good idea to have its prototype anyway 

Okay I understood I needed a class functions to use functions so I did it, thanks!
Okay I understood I needed a class functions to use functions so I did it,

Whatever. That's the exact opposite of what I said. It is idiotic to create a Functions class.
This was my first topic and it is very disorganized so I will solve it and open another one.
Topic archived. No new replies allowed.