'expression' was not declared in this scope

Hi guys:

I have a calculator program that I need to assemble. Ive got 3 dependent functions, they are called:
1.- expression.
2.- primary.
3.- term.
I need to put the all together working. Someone said he did it by putting each function in a class. Therefore I did the same.
Here is the expression function class:
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 FUNCTIONS_H
#define FUNCTIONS_H
#include "token_stream.h"
#include "term.h"

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


#endif // FUNCTIONS_H 


Here is the primary function class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef PRIMARY_H
#define PRIMARY_H
#include "token_stream.h"
#include "functions.h"

double primary( Token_stream& ts )
{
    Token t3{ ts.get( ) };
    switch( t3.getkind())
    {
    case '9': return t3.getvalue();
    case '(': {
        double d3{ expression( ts ) };
        if( ts.get().getkind() != ')' ) error( "keine rechte Klammer" );
        return d3;
    }
    default: error( "kein Primary" );
    }
}

#endif // PRIMARY_H 

And here the term function class:
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
#ifndef TERM_H
#define TERM_H
#include "primary.h"
#include "token_stream.h"

double term( Token_stream& ts )
{
    double d2{ primary( ts ) };
    Token t2{};
    while( true )
    {
        t2 = ts.get();
        switch( t2.getkind() )
        {
        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;
        }
    }
}
#endif // TERM_H


Now I just should include one in each other and everything would work! That´s what they told me... But it doesn´t. In the primary function, line 14, I get this announcement when compiling:

'expression' was not declared in this scope
double d3{ expression( ts ) };
^

And I ask myself why? I added the expression class (called functions.h). And somehow it doesn´t work.

What is happening? Hope you help me
Last edited on
I added the expression class


First expression() is a function not a class, and second executable code should not be in a header file.

All three of your headers should be source files (.cpp) and be added to your project to be compiled, not #included.

You would then need a "header" file to prototype each of those functions.

And don't forget what I told you in your other topic about always returning values when you promise to return a value.


EDIT: PLEASE STOP OPENING NEW TOPICS FOR THIS EXISTING PROBLEM, IT MAKES FOLLOWING THE PROGRESSION MUCH HARDER!

Last edited on
You have a circular dependency.

functions.h includes term.h, term.h includes primary.h, primary.h tries to include functions.h but the include guard prevents the content of functions.h from being included again so when the primary function is being defined the expression function has not yet been defined.

This is one of the reasons why we often split code into source (.cpp) and header (.h) files. If you just declare the functions in the header files you don't need to include the other headers so the circular dependency goes away.

functions.h
1
2
3
4
5
6
7
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include "token_stream.h"

double expression(Token_stream &ts);

#endif // FUNCTIONS_H  

primary.h
1
2
3
4
5
6
7
#ifndef PRIMARY_H
#define PRIMARY_H
#include "token_stream.h"

double primary( Token_stream& ts );

#endif // PRIMARY_H  

term.h
1
2
3
4
5
6
7
#ifndef TERM_H
#define TERM_H
#include "token_stream.h"

double term( Token_stream& ts );

#endif // TERM_H 


If Token_stream is a class you can get rid of #include "token_stream.h" as well by using a forward declaration.

1
2
#include "token_stream.h"
class Token_stream;


Inside the source files, where you put the function definitions, you can include the headers that you need without running into problems.

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

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

primary.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "primary.h"
#include "functions.h"
#include "token_stream.h"

double primary( Token_stream& ts )
{
    Token t3{ ts.get( ) };
    switch( t3.getkind())
    {
    case '9': return t3.getvalue();
    case '(': {
        double d3{ expression( ts ) };
        if( ts.get().getkind() != ')' ) error( "keine rechte Klammer" );
        return d3;
    }
    default: error( "kein Primary" );
    }
}

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
#include "term.h"
#include "primary.h"
#include "token_stream.h"

double term( Token_stream& ts )
{
    double d2{ primary( ts ) };
    Token t2{};
    while( true )
    {
        t2 = ts.get();
        switch( t2.getkind() )
        {
        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;
        }
    }
}
Last edited on
Generally you want to put implementations in .cpp files and declarations in .h files with their include guards, etc.

But it's not the end of the world that you decided to implement a function (not a class!) expression() in global space in what appears to be the file "functions.h". Since this is a function, you were probably looking for
double d3 = expression( ts );
and not an initializer list syntax.
Edit: nevermind, I guess that's legal. Circ dependency, as Peter neatly tracked down, sounds more likely.
You'd still want to try to avoid global functions like that -- put them in classes or at the least namespaces.
Last edited on
Hi guys,

thank you so much for your help. I apologize if I have been posting too much or doing unintelligent code.

Thanks to Peter87 because now I dont have more compiling problems from the .h and .cpp files. Thanks to everyone explaining it, I understood it.

Now I have another problem with the program. I will write about it here because people already know the code.

I get this error:
multiple definition of `error(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'

It´s in a Header file called "myerror.h". Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef MYERROR_H
#define MYERROR_H

#include <stdexcept>
#include <string>
using std::string;

//L01G4 S27/35
void error(const string& s ) { throw std::runtime_error{ s }; }
void error(const string& s1, string& s2 ) { error( s1 + s2 ); }

#endif // MYERROR_H 


I know it´s because I have 2 functions that have the same name. But I have some doubts because:
1.- When commenting out the void error with 2 parameters (here the code):

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef MYERROR_H
#define MYERROR_H

#include <stdexcept>
#include <string>
using std::string;

//L01G4 S27/35
void error(const string& s ) { throw std::runtime_error{ s }; }
//void error(const string& s1, string& s2 ) { error( s1 + s2 ); }

#endif // MYERROR_H 


I receive almost the same announcement:
multiple definition of `error(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'

2.- Because the professor gave us that header file and somehow it worked in his computer without any problem...

Hope you help me!
I know it´s because I have 2 functions that have the same name.

No, that's not the problem. The problem is that the same function is being defined multiple times, once for each source file that includes myerror.h (either directly or indirectly through another header), and that is not allowed for regular functions.

This is another reason why we split functions into header and source files. You can solve this problem the same way as your previous problem.


Another option is to mark the functions as inline.

 
inline void error(const string& s ) { throw std::runtime_error{ s }; }

This will allow you to define the function in the header file, thanks to special rules allowing multiple definitions of inline functions, but note that many compilers will take this as a hint to inline the function (which is an optimization technique) which might or might not be what you want.
Last edited on
Thank you!
It compiled. I decided to just instead of using that error function overall I would just put

throw std::runtime_error{}

Finally!!!

Greetings (y) (y)
Topic archived. No new replies allowed.