This is my first time to try using STL maps. The code looks correct as far as I can tell, but when I try to compile a test file that does nothing but include the header for the class and declare a variable of that class, I am getting compiler errors saying that the map members of my class are not declared in the scope of my function definitions. I am also getting an error that seems to be saying that there is no matching call error for a call to map::insert. Any help with finding my mistakes would be appreciated. Below I have included the compiler errors, my header (.h) file, and my implementation file (.cpp) file I have put comments above the lines in my code that the compiler is complaining about to highlight them. Thanks in advance for any advice.

Here are the compiler errors:

    RefEnv.cpp: In function ‘std::_Rb_tree_iterator<std::pair<const std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, VarIdent> > get_var(std::string)’:
    RefEnv.cpp:45: error: ‘var’ was not declared in this scope
    RefEnv.cpp: In function ‘std::_Rb_tree_iterator<std::pair<const std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, FuncIdent> > get_func(std::string)’:
    RefEnv.cpp:58: error: ‘func’ was not declared in this scope
    RefEnv.cpp: In member function ‘bool RefEnv::insert_func(Type, std::string, std::string)’:
    RefEnv.cpp:104: error: no matching function for call to ‘std::pair<std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, VarIdent>::pair(std::string&, FuncIdent&)’
    /usr/include/c++/4.4/bits/stl_pair.h:83: note: candidates are: std::pair<_T1, _T2>::pair(const _T1&,
    const _T2&) [with _T1 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 =
    VarIdent]
    /usr/include/c++/4.4/bits/stl_pair.h:79: note:                 std::pair<_T1, _T2>::pair() [with _T1 =
    std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = VarIdent]
    /usr/include/c++/4.4/bits/stl_pair.h:68: note:                 std::pair<std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, VarIdent>::pair(const std::pair<std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, VarIdent>&)

Here is my header file:

    #include <map>
    #include <string>

    #ifndef REFENV_H
    #define REFENV_H

    enum Type {INT, SEM, PRCD, PRCS};

    struct FuncIdent{
      std::string stringName;   //string name associated with addr
      Type type;          //type attribute
      size_t addr;        //array index in func table
    };


    struct VarIdent{
      Type type;          //type attribute
      bool paramFlag;     //true if the variable is a function parameter
      size_t addr;        //array index in func table
    };


    class RefEnv{
      public:
        //constructor
        RefEnv();

        //set prev pointer
        void set_prev(RefEnv*);

        //get prev
        RefEnv* get_prev();

        //return iterator to VarIdent object in var
        std::map<std::string, VarIdent>::iterator get_var(std::string);

        //return iterator to FuncIdent object in func
        std::map<std::string, FuncIdent>::iterator get_func(std::string); 

        //insert variable attributes in var
        bool insert_var(Type, std::string, bool);   

        //insert function attributes in func 
        bool insert_func(Type, std::string, std::string);


      private:
        RefEnv *prev;     //pointer to previous reference environment

     //Declarations of maps

        std::map<std::string, VarIdent> var;   //table of sem and int attributes
        std::map<std::string, FuncIdent> func; //table of prcd and prcs attributes
    };

    #endif

Here is my implementation file:

    #include "RefEnv.h"
    #include <map>
    #include <string>

    RefEnv::RefEnv() : prev(NULL){
    }

    void RefEnv::set_prev(RefEnv* p){
      //Precondition:
      //  A RefEnv object exists and RefEnv p exists
      //
      //Postcondition:
      //  prev in the first RefEnv object points to RefEnv p

      prev = p;
    }


    RefEnv* RefEnv::get_prev(){
      //Precondition:
      //  A RefEnv object exists
      //
      //Postcondition:
      //  prev is returned as a constant pointer

      return prev;
    }


    std::map<std::string, VarIdent>::iterator get_var(std::string s){
      //Precondition:
      //  A RefEnv object exists
      //
      //Postcondition:
      //  If a VarIdent object is indexed by s,
      //    an iterator to the object is returned
      //  Else the iterator to end is returned

  //The compiler complains that var is not declared in this scope

      return var.find(s);
    }


    std::map<std::string, FuncIdent>::iterator get_func(std::string s){
      //Precondition:
      //  A RefEnv object exists
      //
      //Postcondition:
      //  If a FuncIdent object is indexed by s,
      //    an iterator to the object is returned
      //  Else the iterator to end is returned

 //The compiler complains that func is not declared in this scope

      return func.find(s);
    }


    bool RefEnv::insert_var(Type t, std::string key, bool p){
      //Precondition:
      //  A RefEnv object exists
      //
      //Postcondition:
      //  If there is not a VarIdent object indexed by key in var,
      //    an object with type t and paramFlag p is inserted
      //    and true is returned
      //  Else false is returned

      VarIdent vi;

      vi.type = t;
      vi.paramFlag = p;
      vi.addr = var.size();

      std::pair<std::map<std::string, VarIdent>::iterator, bool> inserted;

      inserted = var.insert(std::pair<std::string, VarIdent>(key, vi));

      return inserted.second;
    }


    bool RefEnv::insert_func(Type t, std::string key, std::string n){
      //Precondition:
      //  A RefEnv object exists
      //
      //Postcondition:
      //  If there is not a FuncIdent object indexed by key in func,
      //    an object with type t and paramFlag p is inserted
      //    and true is returned
      //  Else false is returned

      FuncIdent vi;

      vi.type = t;
      vi.stringName = n;
      vi.addr = func.size();

      std::pair<std::map<std::string, VarIdent>::iterator, bool> inserted;

//The compiler says there is no matching function call for the line below

      inserted = func.insert(std::pair<std::string, VarIdent>(key, vi));

      return inserted.second;
    }

Edited 4 Years Ago by bgx90: correct formatting

You forgot to put the RefEnv:: infront of the two functions get_var and get_func.

std::map<std::string, VarIdent>::iterator  RefEnv::get_var(std::string s){
std::map<std::string, FuncIdent>::iterator  RefEnv::get_func(std::string s){

And you have the wrong type for the second map template para.

bool RefEnv::insert_func(Type t, std::string key, std::string n){
      //Precondition:
      //  A RefEnv object exists
      //
      //Postcondition:
      //  If there is not a FuncIdent object indexed by key in func,
      //    an object with type t and paramFlag p is inserted
      //    and true is returned
      //  Else false is returned

      FuncIdent vi;

      vi.type = t;
      vi.stringName = n;
      vi.addr = func.size();

      //--------------------------------------------------------------
      // You had VarIdent, should be FuncIdent
      std::pair<std::map<std::string, FuncIdent>::iterator, bool> inserted;

      //--------------------------------------------------------------
      // I changed the pair to make_pair, you issue was you had
      // inserted = func.insert(std::pair<std::string, VarIdent>(key, vi));
      // but the second should be FuncIdent not VarIdent
      inserted = func.insert(std::make_pair(key, vi));

      return inserted.second;
    }

With changes it compiled for me.

Thanks for pointing that out. However, I stll get some errors when compiling after making the changes. What compiler are you using? I am using g++. Any idea what these errors mean?

    user@debianComputer:~$ g++ -o test.cpp RefEnv.cpp
    In file included from /usr/include/c++/4.4/bits/stl_algobase.h:66,
                     from /usr/include/c++/4.4/bits/stl_tree.h:62,
                     from /usr/include/c++/4.4/map:60,
                     from RefEnv.h:5,
                     from RefEnv.cpp:5:
    /usr/include/c++/4.4/bits/stl_pair.h: In constructor ‘std::pair<_T1,
    _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 =
    std::_Rb_tree_iterator<std::pair<const std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, FuncIdent> >, _U2 = bool, _T1 =
    std::_Rb_tree_iterator<std::pair<const std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, VarIdent> >, _T2 = bool]’:
    RefEnv.cpp:104:   instantiated from here
    /usr/include/c++/4.4/bits/stl_pair.h:101: error: no matching function for call
    to ‘std::_Rb_tree_iterator<std::pair<const std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, VarIdent> >::_Rb
    _tree_iterator(const std::_Rb_tree_iterator<std::pair<const std::basic_
    string<char, std::char_traits<char>, std::allocator<char> >, FuncIdent> >&)’
    /usr/include/c++/4.4/bits/stl_tree.h:170: note: candidates are:
    std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator(std::_Rb_tree_node<_Tp>*) [with
    _Tp = std::pair<const std::basic_string<char, std::char_traits<char>,
    std::allocator<char> >, VarIdent>]
    /usr/include/c++/4.4/bits/stl_tree.h:166: note:  
    std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator() [with _Tp = std::pair<const
    std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 
    VarIdent>]
    /usr/include/c++/4.4/bits/stl_tree.h:154: note:  
    std::_Rb_tree_iterator<std::pair<const std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, VarIdent> >::_
    Rb_tree_iterator(const
    std::_Rb_tree_iterator<std::pair<const std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >, VarIdent> >&)

Oops. I missed the make_pair part. This is what the function looks like now:

bool RefEnv::insert_func(Type t, std::string key, std::string n){
  //Precondition:
  //  A RefEnv object exists
  //
  //Postcondition:
  //  If there is not a FuncIdent object indexed by key in func,
  //    an object with type t and paramFlag p is inserted
  //    and true is returned
  //  Else false is returned

  FuncIdent vi;

  vi.type = t;
  vi.stringName = n;
  vi.addr = func.size();

  std::pair<std::map<std::string, FuncIdent>::iterator, bool> inserted;

  inserted = func.insert(std::make_pair(key, vi));

  return inserted.second;

However when I try to compile a test program that includeds RefEnv.h and has an empty body, g++ gives this error and deletes my test program file:

user@debianComputer:~$ g++ -o test.cpp RefEnv.cpp
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status

Did you change both line 100 & 104 to be FuncIdent

std::pair<std::map<std::string, FuncIdent>::iterator, bool> inserted;
inserted = func.insert(std::pair<std::string, FuncIdent>(key, vi));



$ g++ -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~105/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)

Edited 4 Years Ago by histrungalot: Adding

The -o is to specify the output of the compilation, so, when you right:

$ g++ -o test.cpp RefEnv.cpp

You are telling the compiler to compile RefEnv.cpp and produce an executable file called "test.cpp", and because RefEnv.cpp doesn't have the main function, you get the error that you get. So, you need to write this:

$ g++ -Wall test.cpp RefEnv.cpp -o test.exe

(I added -Wall which you should always use).

Or, if for a unix system:

$ g++ -Wall test.cpp RefEnv.cpp -o test

Aha! I am so stupid! It's been a while since I fooled around with compiling and linking files with C++, and I was forgetting to give the name of the executable file. Thanks for your help, histrungalot. By the way, I have not read anything about the use of make_pair in conjunction with maps and their functions. Is there a reason to use inserted = func.insert(std::make_pair(key, vi)); instead of inserted = func.insert(std::pair<std::string, FuncIdent>(key, vi)); other than the obvious benefit of fewer keystrokes?

Thanks for the tips, histrungalot and Mike. Mike, I am sorry if it looked like I disregarded your post; it was not visible when I last posted.

This question has already been answered. Start a new discussion instead.