Doing some Metaprogramming with c++11.
I want to build an EnumWrapper which can be used for switch statements and as keywords for maps but still has object-like properties, like Java Enumerations.
Having the classes:
#include <string>
#include <vector>
template<typename T, int len>
class Enum
{
private:
typename T::Value value; // invalid use of incomplete Type Planet
public:
Enum() = delete;
constexpr Enum( typename T::Value key ) : value( key ) // invalid use of incomplete Type Planet
{
}
// Allow switch and comparisons.
operator typename T::Value() const // invalid use of incomplete Type Planet
{
return value;
}
T& operator=( const T& other )
{
this->value = other.value;
return *this;
}
inline typename T::Value getValue() // invalid use of incomplete Type Planet
{
return value;
}
explicit operator bool() = delete;
Enum& operator=( const Enum& p )
{
this->value = p.value;
return *this;
}
static inline int length()
{
return len;
}
static std::vector<T> values()
{
std::vector<T> values;
values.reserve( length() );
for ( int i = 0; i < length(); i++ )
{
values.push_back( (typename T::Value)i ); // This is fine for some reason
}
return values;
}
static T getMember( std::string name )
{
for ( T p : values() )
{
if ( p.name() == name )
{
return p;
}
}
}
};
class Planet : Enum<Planet, 3>
{
public:
enum Value
{
MERCURY,
VENUS,
EARTH
}
std::string name()
{
switch(this->getValue())
{
case MERCURY:
return "Mercury";
case EARTH:
return "Mercury";
case VENUS:
return "Mercury";
}
}
};
The compiler gives several "invalid use of incomplete Type Planet" messages.
When merging the classes into one single class, the code compiles and works as intendet. But reuseablility and maintainability is not given with a merged approach.
Can someone help me with this error messages?
Just tell me, if further information is needed or wanted.
Edit: My inteded use is something like this:
int main()
{
Planet planet = Planet::EARTH;
Planet invalidPlanet = Planet( (Planet::Value)5 );
// attributes with enum working
std::cout << "My Planet is named " << planet.name() << std::endl;
Planet venus = Planet::VENUS;
std::cout << "Gravity of Venus is " << venus.gravitation() << std::endl;
// Switch working
switch ( planet )
{
case Planet::VENUS:
std::cout << "Venus found." << std::endl;
break;
case Planet::EARTH:
std::cout << "Earth found." << std::endl;
break;
default:
std::cout << "Nothing found." << std::endl;
break;
}
// simple comparison
bool isEarth = planet == Planet::EARTH; // true
bool isVenus = planet == Planet::VENUS; // false
std::cout << "Planet is earth: " << ( isEarth ? "true" : "false" ) << std::endl;
std::cout << "Planet is venus: " << ( isVenus ? "true" : "false" ) << std::endl;
// works in Map
std::map<Planet, std::string> myMap;
myMap[ planet ] = "MyEarth";
std::cout << "chosen planet: " << myMap[ Planet::MERCURY ] << std::endl;
std::cout << "chosen planet: " << myMap[ Planet::EARTH ] << std::endl;
// Map is not bound to object but bound to enum integer
Planet fakeEarth = Planet::EARTH;
std::cout << "chosen planet: " << myMap[ fakeEarth ] << std::endl;
return 1;
}
Aucun commentaire:
Enregistrer un commentaire