1

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;
}
hopittyhop
  • 119
  • 12
  • 2
    *Where* do you get the error? Can you please mark it out in the source with a comment? – Some programmer dude Feb 01 '16 at 13:40
  • Done. I'm getting it at the ` cout << endl << p->first.getFileName() << '\t' << p->first.getFileName() << '\t' << p->second.getFileType() << endl;` – hopittyhop Feb 01 '16 at 13:42
  • 1
    I'm not sure if I understand you right, but do you want to print out the enumeration value? Do you want to print it as a string? Or as its numerical value? – Some programmer dude Feb 01 '16 at 13:45
  • Yes, I want to print out the value of the enum, but as a string (aka - 'Archive'. 'ReadOnly' etc.). I did p->second, as you suggested and I had to overload an << operator, to be able to print it out, but it prints out the numerical value of the enum. :) What should I do to get the string value? – hopittyhop Feb 01 '16 at 14:00
  • An unrelated note about your file-type design: It doesn't really makes sense as those types are not mutually exclusive. A file can by a hidden, read-only system archive file for example. – Some programmer dude Feb 01 '16 at 14:00

3 Answers3

1

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;
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • @hopittyhop The stream must be passed by reference not by value, updated my answer. – Some programmer dude Feb 01 '16 at 14:13
  • Yes, I saw it now. After editing it a bit, because my FileType is without capital T and putting curly brackets at the beginning of the function I still get an initialization error `error C2552: 'types' : non-aggregates cannot be initialized with initializer list` :( Any idea on this? – hopittyhop Feb 01 '16 at 14:22
  • @hopittyhop Ah, it seems you don't have C++11 enabled (or to old compiler so it's not supported), then your only choice is to use the `switch` version. I'll edit the answer to put it back. – Some programmer dude Feb 01 '16 at 14:23
  • There is also https://github.com/aantron/better-enums for reading enums from and writing to string, if you're willing to use a library. Disclaimer, I am the author. – antron Feb 01 '16 at 14:24
  • @Joachim Pileborg I'm using Visual Studio 2012, I thought C++11 is enabled by default on it or am I wrong? – hopittyhop Feb 01 '16 at 14:26
  • It works using the switch statement!!! Thank you!! But I do have a new problem.. all my files are printed as 'not-supported' on the console :D In my test file I got 5 lines: every line contains for example : File1(fileName) 1000(fileSize) Archive(fileType) , guess I have to work on why am I getting every file as 'not-supported' now. – hopittyhop Feb 01 '16 at 14:32
  • Oh, nevermind... I had to put my if-else (for the enum check), inside the while, where I iterate on my multimap :) Silly me. Thanks for your help @Joachim Pileborg!!! – hopittyhop Feb 01 '16 at 14:34
0
p->second.getFileType()

The map being accessed here appears to be:

multimap <CFile, Filetype> m_DirectoryMap;

The second component in the map is Filetype, which is an enum POD. It is not some kind of a class or a function that implements the () operator.

Community
  • 1
  • 1
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • hopittyhop isn't calling the `operator()`, though. They're calling `getFileType()` member function. Otherwise the answer applies. – eerorika Feb 01 '16 at 13:47
0

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

It's not a pointer. It's an iterator. But yes, the error indeed does state that you cannot access getFileType member function. Your enum has no such member function and in fact, enums cannot have member functions.

Can I do something to access and read the value of the enum

Yes. In the case of your iterator, the value is in p->second.

(so I can print it out on the console)

You'll need to define an overload for operator<<(std::ostream, const FileType&) in order to pass the value to a stream.

eerorika
  • 232,697
  • 12
  • 197
  • 326