silent_coder silent_coder - 16 days ago 11
C++ Question

Trouble with forward declaration: incomplete type 'enums::Category' used in nested name specifier

I want to have a wrapper around enum which will give me chance to convert it to string and vice-versa.

Base class is the following:

template<typename TEnum>
class StringConvertedEnum {
public:
static std::string toString(TEnum e);

static TEnum toEnum(std::string &str);

protected:
static const std::map<std::string, TEnum> _stringMapping;
static const std::map<TEnum, std::string> _enumMapping;
};


And then I want to have something like this:

class Category : public StringConvertedEnum<Category::Enum> {
public:
enum Enum {
Category1,
Category2,
OTHER
};
};


However at the current moment it's not compile via this error:

incomplete type 'enums::Category' used in nested name specifier


How to fix this problem?

Answer

Because Enum is declared inside your class, it doesn't exist before its declaration when you're specifying that Category inherits StringConvertedEnum. That is an incomplete type, see relevant part of the standard "3.3.2 Point of declaration [basic.scope.pdecl]" (thanks AndyG for pointing this out in the comments).

The easiest way to solve the problem is to declare Enum outside Category:

enum Enum {
    Category1,
    Category2,
    OTHER
};

class Category : public StringConvertedEnum<Enum> {};

This follows Zen of Python, even if we're speaking about C++:

Flat is better than nested.

The second easiest way is to declare a base class:

class BaseCategory {
public:
    enum Enum {
        Category1,
        Category2,
        OTHER
    };
};
class Category : public BaseCategory, public StringConvertedEnum<BaseCategory::Enum> {};

As also pointed in the comments, you should consider scoped enums if you're using modern C++.

Comments