Search code examples
c++c++11enumsmultimap

Reading private enums that are stored in a multimap as value


I have some trouble accessing and printing the value of an enum class, that is stored inside a multimap, as a value. The error I'm getting is:

error C2228: left of '.getFileType' must have class/struct/union

From what I understand, my pointer is pointing at the enum class and it can't access the getFileType(); function.

Can I do something to access and read the value of the enum (so I can print it out on the console)? My multimap pair must be like the one I did .

Any suggestions are well appreciated, since I really can't work this out with my head.

Thanks for your time!

#include <iostream>
#include <string>
#include <map>
#include <utility>
#include <fstream>

using namespace std;

fstream fp;

class CFile {
    string m_strFile;
    unsigned int m_size;
public:
    CFile () { m_strFile = ""; m_size = 0; }
    CFile (string name, int size ) { m_strFile = name; m_size = size; }
    string getFileName () const { return m_strFile; }
    int getFileSize () const { return m_size; }
    void setFileSize ( int size ) { m_size = size; }
    bool operator< (CFile& obj) {
        return ( m_size < obj.m_size );
    }
    bool operator== (const CFile& obj) {
        return ( m_size == obj.m_size );
    }
    friend ostream& operator<< ( ostream& ost, const CFile& obj ) {
        return ost << obj.m_strFile << obj.m_size;
    }
    friend istream& operator>> ( istream& ist, CFile& obj ) {
        return ist >> obj.m_strFile >> obj.m_size;
    }
    static bool Greater(const CFile& obj1, const CFile& obj2) {
        if ( obj1.m_size > obj2.m_size )
            return true;
        else 
            return false;
    }
};

bool operator< (CFile obj1, CFile obj2) {
    return obj1.getFileName()<obj2.getFileName();
}

class CDirectory {
    string m_strDirectory;
    enum class Filetype {
        Archive, Hidden, ReadOnly, System, FileNotSupported
    };
    Filetype filetype;
    multimap <CFile, Filetype> m_DirectoryMap;
public:
    Filetype getFileType();
    CDirectory (string n) {
              fp.open (n, ios::in);
              string dirName, fileName,  fType;
              int fileSize;
              fp >> dirName;
              m_strDirectory = dirName;
              if (fType == "Archive")
                  filetype = Filetype::Archive;
              else if (fType == "Hidden")
                  filetype = Filetype::Hidden;
              else if (fType == "ReadOnly")
                  filetype = Filetype::ReadOnly;
              else if (fType == "System")
                  filetype = Filetype::System;
              else 
                  filetype = Filetype::FileNotSupported;
              while (fp >> fileName >> fileSize >> fType) {
                      CFile obj (fileName, fileSize);
                      m_DirectoryMap.insert(pair<CFile, Filetype>(CFile(obj.getFileName(), obj.getFileSize()), Filetype(filetype)));
              }
              multimap<CFile, Filetype>::iterator p = m_DirectoryMap.begin();
              while ( p != m_DirectoryMap.end()) {
                cout << endl << p->first.getFileName() << '\t' << p->first.getFileName() << '\t' << p->second.getFileType() << endl; // im getting the error here, at p->second.getFileType()
              }
    }
    string getDirectory () { return m_strDirectory; }
};

CDirectory::Filetype CDirectory::getFileType() {
        return filetype;
}

int main () {
    CDirectory obj("test.txt");
    system("pause");
    return 0;
}

Solution

  • If you want to print out the value of p->second there are basically two different solutions, depending on what you actually want to be printed.

    If you want to print the numerical value of the enumeration you can use static_cast, e.g.

    std::cout << static_cast<int>(p->second);
    

    If you want to print a string or some other representation of the enumeration, you need to overload the "output" operator <<. Perhaps something like this

    class CDirectory {
        ...
    
        friend std::ostream& operator<<(std::ostream& os, FileType const type)
        {
            static std::map<FileType, std::string> const types = {
                { FileType::Archive, "archive" },
                { FileType::Hidden, "hidden" },
                { FileType::ReadOnly, "read-only" },
                { FileType::System, "system" },
                { FileType::FileNotSupported, "not-supported" }
            };
            return os << types[type];
        }
    
        ...
    };
    

    Then you can simply do

    std::cout << p->second;
    

    Using switch instead of a map:

    friend std::ostream& operator<<(std::ostream& os, FileType const type)
    {
        switch (type)
        {
        case FileType::Archive:
            os << "archive";
            break;
        case FileType::Hidden:
            os << "hidden";
            break;
        case FileType::ReadOnly
            os << "read-only";
            break;
        case FileType::System
            os << "system";
            break;
        case FileType::FileNotSupported
            os << "not-supported";
            break;
        }
    
        return os;
    }