简体   繁体   中英

C++ static struct template method to return enum type

I don't really know c++ but I have been messing around with it for some time now, although I know I should really take the time to learn it.

Anyway the problem I have here is with a static struct, I am uncertain if the structure of this is correct.

enum ItemTypes_t {  
    ITEM_TYPE_KEY,
    ITEM_TYPE_MAGICFIELD,
    ITEM_TYPE_DEPOT,
    ITEM_TYPE_REWARDCHEST,
    ITEM_TYPE_MAILBOX,
    ITEM_TYPE_TRASHHOLDER,
    ITEM_TYPE_TELEPORT,
    ITEM_TYPE_DOOR,
    ITEM_TYPE_BED,
    ITEM_TYPE_RUNE
};

template <typename T>
static struct tTypes {
public:
    const char* name;
    T value;
    T getEnums(std::string itemName);
};

tTypes<ItemTypes_t>itemEnum[] = {
    { "key", ITEM_TYPE_KEY },
    { "magicfield", ITEM_TYPE_MAGICFIELD },
    { "depot", ITEM_TYPE_DEPOT },
    { "rewardchest", ITEM_TYPE_REWARDCHEST },
    { "mailbox", ITEM_TYPE_MAILBOX },
    { "trashholder", ITEM_TYPE_TRASHHOLDER },
    { "teleport", ITEM_TYPE_TELEPORT },
    { "door", ITEM_TYPE_DOOR },
    { "bed", ITEM_TYPE_BED },
    { "rune", ITEM_TYPE_RUNE }
};

ItemTypes_t tTypes<ItemTypes_t>::getEnums(std::string itemName) {
    for (int i = 0; itemEnum[i].name; i++) {
        if (itemEnum[i].name == find) {
            return itemEnum[i].value;
        }
    }
    return;
};

I create an instance of it like this.

tTypes<ItemTypes_t> itemType = tTypes<ItemTypes_t>();

And then call it like this.

ItemTypes_t storage;

storage = itemType.getEnums("some item name is passed here as a string");

There are no errors but I really don't understand the structure or don't even know if it will work.

Edit: Here are some errors

error C2988: unrecognizable template declaration/definition
error C2059: syntax error: '<end Parse>'
error C2977: 'tTypes': too many template arguments
note: see declaration of 'tTypes'
error C2977: 'tTypes': too many template arguments
note: see declaration of 'tTypes'
error C2027: use of undefined type 'tTypes'
note: see declaration of 'tTypes'
error C2027: use of undefined type 'tTypes'
note: see declaration of 'tTypes'
error C2027: use of undefined type 'tTypes'
note: see declaration of 'tTypes'
error C2561: 'getEnums': function must return a value
note: see declaration of 'getEnums

I tried using a map but that didn't work

std::map<std::string, ItemTypes_t> tTypes = {
    { "key", ITEM_TYPE_KEY },
    { "magicfield", ITEM_TYPE_MAGICFIELD },
    { "depot", ITEM_TYPE_DEPOT },
    { "rewardchest", ITEM_TYPE_REWARDCHEST },
    { "mailbox", ITEM_TYPE_MAILBOX },
    { "trashholder", ITEM_TYPE_TRASHHOLDER },
    { "teleport", ITEM_TYPE_TELEPORT },
    { "door", ITEM_TYPE_DOOR },
    { "bed", ITEM_TYPE_BED },
    { "rune", ITEM_TYPE_RUNE },
};

Edit 2:

I used the c++ compiler online to test how I think it should work and it works fine (the map) but when I try it in the project it doesn't work at all.

This is just a really basic example.

#include <iostream>
#include <map>

using namespace std;

enum a : unsigned int {
    RED = 23, BLACK = 43, BLUE = 56
};

map<string, a> colors = {
    {"black", BLACK},
    {"green", RED},
    {"yellow", BLUE}
};

int main()
{
   cout << "test map " << colors["green"] << endl; 

   return 0;
}

This is the results

sh-4.3$ g++ -std=c++11 -o main *.cpp                                                                                                                                
sh-4.3$ main                                                                                                                                                        
test map 23 

Thanks everyone for the advice, the problem isn't the map or well the map works.. the monstrosity I tried to construct with the static struct template was obviously wrong..

The real problem here is where it is reading the strings from.

I'll just explain, normally this data is read from an xml file but I constructed some code to generate a lua table from the parsing of the xml file so that I could re-write the function to load the lua table which had issues of nesting errors so this is why i am using a map, actually several.

I've been working on this for hours, so its natural to over look something, the strings in the code are not problem nor are maps, its the lua file, some of its properties are different character case.. so naturally when I scan an index of the map even tho its the same spelled word its a different character case.

Solution:

The easiest solution would be for me to lowercase the properties when I am constructing the lua table.

Conclusion:

That worked, instead of literally 50k unread properties now I only am down to maybe 20 or 30 unread properties.. thanks everyone for help, I'll definitely check out those books!

You define yout getEnums function like this:

ItemTypes_t tTypes<ItemTypes_t>::getEnums(std::string itemName) { ... }

However that's not how a member function of a templated class is defined. What this is, is a specialization and you can't specialize a single member of a templated structure, you must specialize the whole structure.

You should instead do

template<typename T>
T tTypes<T>::getEnums(std::string itemName) { ... }

There are other things that you should look at. Like the mapping between the strings and the enumeration values which should probably be passed to the tTypes class as an argument to the constructor and stored internally inside the class.

Your code can be implemented with std::map and using a singleton class as follows:

#include <map>
#include <string>

enum class repo_t {ITEM_TYPE_MAGICFIELD,ITEM_TYPE_DEPOT}; //etc

class repo
{
   private:
     std::map<std::string,repo_t> items;
     repo()
     {
     items.insert(std::make_pair("magicfield", repo_t::ITEM_TYPE_MAGICFIELD));
     items.insert(std::make_pair("depot", repo_t::ITEM_TYPE_DEPOT ));
     items.insert(std::make_pair("rewardchest",repo_t::ITEM_TYPE_REWARDCHEST ));
         //etc
      } 

   public:

   static repo*& get_instance()
    {
        static repo* obj(new repo());
        return obj;
    }

    ~repo(){}

    bool find(std::string key, repo_t& result)
    {
       auto it = items.find(key);
       if(it ==  items.end())
             return false;
       result = *it;
       return true;
    }


};

//usage

void main()
{
    repo_t result;
    bool found = repo::get_instance()->find("magicfield",result);
    if(found)
    {
       // do something with result
    }
    else
    {
      // key not found
    }


}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM