I know that enum inheritance is not possible in c++, but I am looking for specific data structure that simply fit into my case. Suppose I have these two enums:
enum Fruit { apple, orange};
enum Drink { water, milk};
I want a parent for these two that I can use as parameter in this abstract method
void LetsEat(Eatable eatable){}
They are going to be used as simple switches, and basically I want to keep my code clean and type safe. I wonder if I will be forced to use inherited classes that needs to be initialized. It is too much for this simple problem.
Speaking very generally, enums are just dressed up ints.
enum Fruit { apple, orange};
If you look at the compiled code, you will discover that an apple will be represented by the value 0, and an orange will be represented by the value 1.
enum Drink { water, milk};
Same thing here will happen here. water will be represented by value 0, and milk will be represented by value 1. You can begin to see the obvious problem here.
One, a slightly primitive, solution is equivalent to letting a bull loose in the china shop:
enum Drink { water=2, milk=3};
Now you could cook something up where you're passing in a int value and figure out what exactly was passed in, by its value.
But this will likely require plenty of ugly casts, everywhere. The resulting code, if posted to Stackoverflow, will likely to attract downvotes.
The downvotes will be because there are cleaner solutions that are available in modern, post C++17 world. For starters, you can switch to enum classes.
enum class Fruit { apple, orange};
enum class Drink { water, milk};
This gains additional type-safety. It's not as easy, any more, to assign a Fruit to a Drink. Your C++ compiler will bark, very loudly, in many situations where it would raise a warning. Your C++ compiler will help you find even more bugs, in your code. It is true that this will require a little bit more typing. You will always have to specify enumerated values everywhere with full qualification, i.e. Fruit::apple and Drink::water, when in your existing code a mere apple and water will suffice. But a few extra typed characters is a small price to pay for more type-safe code, and for being able to simply declare:
typedef std::variant<Fruit, Drink> Eatable;
and simply do what you always wanted:
void LetsEat(Eatable eatable){}
and everything will work exactly how you wanted it. LetsEat will accept either a Fruit or a Drink as its parameter. It will have to do a little bit more work, to figure out what's in the std::variant, but nobody ever claimed that C++ is easy.
std::variant is one of the more complex templates in the C++ library, and it's not possible to explain how to use it, fully, in a short paragraph or two on Stackoverflow. But this is what's possible, and I'll refer you to your C++ textbook for a complete description of how to use this template.
This sounds like an excellent use case for std::variant.
#include <variant>
#include <iostream>
// Define our enums
enum Fruit { Apple, Orange };
enum Drink { Water, Milk };
// An Eatable is either a Fruit or a Drink
using Eatable = std::variant<Fruit, Drink>;
void letsEat(Eatable eatable) {
// We can use the index() method to figure out which one we have
switch (eatable.index()) {
case 0:
std::cout << "It's a Fruit!" << std::endl;
break;
case 1:
std::cout << "It's a Drink!" << std::endl;
break;
}
}
int main() {
letsEat(Apple);
letsEat(Water);
}
Note that std::variant<Fruit, Drink> is not, strictly speaking, a supertype of Fruit or Drink. Instead, it's a new type altogether but we get implicit conversions from Fruit and Drink to std::variant<Fruit, Drink> via its constructors.
If you're not using C++17, you can use boost::variant from the Boost C++ libraries.
You can use std::variant<T, ...> if you use C++17 or above:
#include <iostream>
#include <variant>
#include <type_traits>
enum Fruit { apple, orange };
enum Drink { water, milk };
using Eatable = std::variant<Fruit, Drink>;
void LetsEat(Eatable const eatable) {
std::visit([] (auto&& v) {
using T = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<T, Fruit>) {
// Now use it like you would use a normal 'Fruit' variable ...
}
if constexpr (std::is_same_v<T, Drink>) {
// Now use it like you would use a normal 'Drink' variable ...
}
}, eatable);
}
int main() {
LetsEat(apple);
}
Alternatively, you could just create a class that is implicitly convertible to either enum type:
class Eatable {
union {
Fruit f;
Drink d;
} u_;
bool has_fruit_;
public:
Eatable(Fruit f) : has_fruit_(true) {
u_.f = f;
};
Eatable(Drink d) : has_fruit_(false) {
u_.d = d;
};
operator Fruit() const {
return u_.f;
}
operator Drink() const {
return u_.d;
}
bool has_fruit() const {
return has_fruit_;
}
};
Then you can use it like this:
void LetsEat(Eatable const eatable) {
if (eatable.has_fruit()) {
Fruit const f = eatable;
switch (f) {
case apple:
std::cout << "Fruit: apple" << std::endl;
break;
case orange:
std::cout << "Fruit: orange" << std::endl;
break;
default: break;
}
} else {
Drink const d = eatable;
switch (d) {
case water:
std::cout << "Drink: water" << std::endl;
break;
case milk:
std::cout << "Drink: milk" << std::endl;
break;
default: break;
}
}
}
Related
int main() {
if(i = 0) {
myclass1 a = "Example1";
}
else {
myclass2 a = "Example2";
}
cout << a << endl;
}
I know a way to do this is by defining it outside the block but what if I have not decided what type a is before checking the condition of i?
If you are able to use c++17 you can use the std::variant or std::any in case your types haven't common base class. These classes are type-safe containers for any or specified types. An example with std::variant can be the following:
#include <iostream>
#include <string>
#include <variant>
int main() {
bool input = false;
std::cin >> input;
std::variant<int, long, double, std::string> myVariant;
if(input)
myVariant = "Example1";
else
myVariant = 3.14;
std::visit([](auto&& arg) { std::cout << arg << std::endl; }, myVariant);
}
Instead of c++17 you also can use the boost::variant or the boost::any.
C++ is a statically typed language, and requires the type of variables being used in the code to be known at compile time.
There's no way to write a C++ program where a statement like std::cout << a; is compiled and the type of a is not known until run-time.
For that you need a dynamically typed language, like for example Python or JavaScript.
int main() {
auto call = [](auto a) {
std::cout << a << std::endl;
};
if(i = 0)
call(myclass1 { "Example1" });
else
call(myclass2 { "Example2" });
}
You could try polymorphism.
Assuming myclass1 and myclass2 "implement" a class called myclass, you can do something like this:
int main() {
myclass*a;
if (i=0) {
a = new myclass1("Example1");
} else {
a = new myclass2("Example2");
}
cout<<*a<<endl;
}
If you want to actively use the type myclass1 or myclass2 later on, you can use dynamic_cast, but depending on your needs and what behaviour you implement in your inherited classes and your base class, thay may not be necessary.
Note I use a raw pointer here, since it's a short-lived object and it's clear the program has ended. I encourage you to read about smart pointers and use them appropriately to avoid memory leaks. Beware memory leaks in some platforms persist until after a reboot, it may be needed to manually free (delete) allocated memory. More about all that here.
This definitively calls for polymorphism, and optionally, if you want to have it a bit more elegant, the factory pattern. The factory pattern is no magic, it just hides the if within a nice wrapper.
Why not another approach, such as e.g. std::variant which is basically a union in disguise? Well, it's nice if you are able to store different kinds of things, or even any kind (std::any) under the same name, but it is not very useful since you also want to do something meaningful with the object. If you want to do completely different, unrelated things, then you can as well have different objects scoped by the if blocks (and with completely different code). If, however, you want to do the same or similar things on different objects, then they (usually) need to be the same or a related type.
Different types typically do not have the same data members or the same publicly accessible member functions. So, doing the same thing on a source code level with different types typically doesn't work (except by coincidence).
But if two classes do have identical subsets on their interfaces, and you want to be able to do it in one or the other way interchangeably, then inheriting from a base class is the most natural and idiomatic thing to do. That's what polymorphism was invented for. Use the idiomatic thing.
(You can get the same net effect of calling functions with the same name on different, unrelated types via a template helper, and presumed that the names that you use exist, that will just work, but it's not nearly as good style, and it causes huge bloat by instanciating the function twice).
I'll try to give you a practical answer that assumes you're used to doing this sort of thing in JavaScript or something and just trying to write code in C++.
First, you should understand that in C++, cout << a. Can actually call a completely different method depending on the type of a. For that reason, it doesn't make any sense to write cout << a when you don't know anything about that type. In fact, you can't do anything at all with a unless you know enough about the type for C++ to decide which method or operator you want to invoke.
If both of your classes have an acceptable common base, then you could do something this:
int main() {
base_class *pa;
my_class1 a1;
my_class2 a2;
if(i = 0) {
a1 = "Example1";
pa = &a1;
}
else {
a2 = "Example2";
pa = &a2;
}
cout << *pa << endl;
}
Note that when you write cout << *pa, you are not necessarily calling the same method that cout << a would use. In the first case you are calling a method that knows how to output all subclasses of base_class, while in the second case you may be calling a method that was written specifically for myclass1 or myclass2.
When there is no acceptable base class, then we just don't write code like that in C++:
int main() {
if(i = 0) {
myclass1 a = "Example1";
cout << a << endl;
}
else {
myclass2 a = "Example2";
cout << a << endl;
}
}
Remember that the two methods being called in these cases can be completely different methods. It's exactly like calling cout.printClass1(a) vs. cout.printClass2(a). C++ lets you use the same name for completely different methods when it can figure out which one you want to call based on the argument types.
JavaScript doesn't have any magic that could automatically choose between printClass1 and printClass2 when you write cout.callWhatever(a), and neither does C++. In both languages, if you have to call completely different methods for myclass1 vs. myclass2, then you write different calls.
I had such code myself, when I was in fact trying different variations of the same code. Then I realized the best option would be to use a preprocessor #if and it solved my problem:
#define VARIATION 2
...
#if VARIATION == 1
myclass1 a = "Example1";
#else
myclass2 a = "Example2";
#endif
I know it probably doesn't solve yours, but at least it is a workaround.
If it is this specific problem I would think that this would be much more easier
int main(){
if(i == 0) //You wrote i=0 !! silly mistake
std::cout << myclass1("Example1");
else
std::cout << myclass2("Example2");
}
or you can choose
template<class T>
void foo(T out)
{
std::cout << out;
}
int main()
{
if( i==0 )
foo(myclass1("ex1"));
else
foo(myclass2("ex2"));
}
else
this is the way to go
And I would advise against using cout here as it may not have overloads to accept your user defined class.
In my code, I am using string IDs. That is good in debug and in code during coding. You can imagine it like this:
MyCar * c = cars->GetCarID("my_car_1");
MyCar * c = cars->GetCarID(variable);
But this is slower in release, because of string - string comparison in GetCarID code.
I would like to have something like this
MyCar * c = cars->GetCarID(CREATE_ID("my_car_1"));
MyCar * c = cars->GetCarID(CREATE_ID(variable));
CREATE_ID - in debug, it will return string that is written in code, in release, it will return int hash or something like that.
How can I achieve this? Or how is this usually solved?
You can wrap your id in a class, something like:
class StringID
{
public:
StringID(const StringID&);
StringID(const char*);
StringID(const std::string&);
...
private:
#if DEBUG
std::string _idAsString;
#endif
int _id;
};
and define common operation for your class, like operator<, operator== and so on. In this way on release build you will have a wrapper over int and on debug build the class will contain the string to make it easier to debug.
For performance reasons you can make id/hash computation constexprand compute it at compile time for string literals (for more info please check this: Computing length of a C string at compile time. Is this really a constexpr?).
With this approach you can catch hash clashes by checking also the strings in debug mode, not only the hashes. As you probably already know, different strings can lead to same hash (unlikely for common english words, but possible) and this will be very difficult to debug without knowing the string that generated the hash.
In debug mode, #define CREATE_ID(x) #x and use cars->GetCarID(CREATE_ID(my_car_1));. In release mode, #define CREATE_ID(x) x, add an enum { my_car_1, ... } and you still use cars->GetCarID(CREATE_ID(my_car_1));
Note that you never use CREATE_ID(variable) but you may use auto variable = CREATE_ID(my_car_id).
You could use enums instead of strings. This way you have readable names for your integers:
enum ID {
my_car_1
, my_train_1
, my_g6_1
};
My approach would be to use enum class. This allows to have typesafe identifier, that is char or int underneath. A simple code example would be:
#include <iostream>
enum class COLOR {
RED
, GREEN
};
std::ostream & operator << (std::ostream & o, const COLOR & a) {
switch(a) {
case COLOR::RED: o << "RED";break;
case COLOR::GREEN: o << "GREEN";break;
default: o << static_cast<int>(a);
}
return o;
}
int main() {
COLOR c = COLOR::RED;
std::cout << c << std::endl;
return 0;
}
The drawback is, that you have to explicitly writeout all identifiers twice - once in class and once in operator.
One of the mayor advantages of enum class is that names are scoped and it does not allow stuff like:
std::string get(COLOR x);
...
get(3); //Compile time error
get(CAR::GOLF);//Compile time error
Judging by your comments on other answers, you can define your own identifier like this:
class MyId {
public:
int id;
static std::unordered_map<int,std::string> names;
};
std::ostream & operator << (std::ostream &o,const MyId & m) {
auto itr = MyId::names.find(m.id);
if(itr!= MyId::names.end()) {
o << itr->second;
} else {
o << "Unknown " << m.id;
}
return o;
}
Its typesafe, theres no more overhead then int, and it is able to survive user input.
I am using same namespace in two different files.
In those files i have 2 enum.
I need to use same identifiers in those enum.
Is there a way to do it?
In first file
first.h
...
namespace foo
{
enum direction
{
NONE,
RIGHT
...
}
}
In second file
second.h
...
namespace foo
{
enum reverse
{
NONE,
LEFT,
...
}
}
This is a sample code.
I need to reuse "NONE".
I need code for visual studio 2008.
(Cannot use : enum class)
If you can use C++11, the best way to achieve what you want is to use "strongly typed enums", declared using the enum class keywords, i.e.
enum class direction
{
NONE,
LEFT
};
enum class reverse
{
NONE,
RIGHT
};
In the rest of your code, you then refer to the enumerators as ns::direction::NONE and ns::reverse::NONE (like in C#, if you're familiar with that language).
If you don't have C++11 available, then you can simulate the same thing by declaring an anonymous enum in an inner namespace, for example
namespace direction {
enum {
NONE,
LEFT
};
}
namespace reverse {
enum {
NONE,
RIGHT
};
}
Again, you then refer to direction::NONE and reverse::NONE, so there is no conflict.
#include <iostream>
#include "first.h"
namespace second
{
#include "second.h"
}
using namespace std;
int main()
{
cout << foo::NONE << " " << second::foo::NONE << endl;
return 0;
}
You may use
direction::NONE
and
reverse::NONE
to distinguish the enumerators provided that the enumerations are defined in different scopes. Otherwise the compiler will issue an error of redefinition of an enumerator.
Here is an example
#include <iostream>
enum A { NONE };
namespace N1
{
enum B { NONE = 1 };
}
int main()
{
enum C { NONE = 2 };
std::cout << A::NONE << '\t' << N1::NONE << '\t' << NONE << std::endl;
return 0;
}
The output is
0 1 2
no, you can't reuse the values from one enum to another.
This is probably NOT the right solution, but you can either use explicit enum values, e.g.
enum ...
{
NONE = 0,
...
};
or rely on the compiler starting with 0 and counting up one for each enumeration (assuming no assignment).
However, they are still not the same enum type, and I think you should consider a different solution. It's not entirely clear from your question what you are actually trying to achieve, but it sounds like you are trying to make a "reverse control", where left becomes right and right becomes left, etc. I would suggest having a getter function that does something like this:
direction GetDirection()
{
if (reverse)
{
switch(curDirection)
{
case LEFT:
return RIGHT;
case RIGHT:
return LEFT;
... deal with other directions that need reversing ...
}
}
return curDirection;
}
Another option is to implement two classes, where one does a "reverse switch", and the other just returns the current direction without reversing.
I'm pretty new to C++ and am having trouble making a pointer point from one class to another. This is what I have, it compiles without error, but doesn't work the way I want it to.
JungleMap *Map;
class JungleMap
{
public:
void goNorth()
{
cout << "You are going north towards the river.\n";
delete[] Map;
RiverMap *Map;
}
}
class RiverMap
{
public:
void goNorth()
{
cout << "You are going north away from the river.\n";
delete[] Map;
JungleMap *Map;
}
}
int main()
{
Map->goNorth();
Map->goNorth();
}
This is what the output is:
You are going north towards the river.
You are going north towards the river.
And this is what I would like the output to be:
You are going north towards the river.
You are going north away from the river.
How do I achieve this? It's really bugging me, especially since it compiles without problems.
Just creating a JungleMap* doesn't create a JungleMap. You formed a pointer, but didn't point it anywhere!
This is particularly dangerous since you then dereference it, and later attempt to delete through it. Yes, this compiles, because a compiler cannot diagnose this in the general case (and is never required to try), but you'll get everything at runtime from silent nothingness, to a crash, to a nuclear explosion.
You are also trying to invoke different functions in two different classes, through changing the type of a pointer (without any inheritance, at that), which is simply not possible and will prevent your code from compiling, even though you've tried to get around it by redeclaring variables locally. I could list a ream of misunderstandings but suffice it to say it's time to read a good introductory C++ book.
I would suggest a combination of inheritance and dynamic allocation, if I knew what you were trying to achieve. A common mistake on SO is to provide nonsense code, then expect us to know what your goal is from that nonsense code; unfortunately we have about as much idea what you really meant to do as the C++ compiler does!
You could make this work (to at least a minimal degree) by creating a base class from which both JungleMap and RiverMap derive. You'd then have a pointer to the base class, which you'd point at an instance of one of the derived classes. You'll also need to rearrange the code somewhat to get it to compile.
class Map {
public:
virtual void goNorth() { cout<<"Sorry, you can't go that way"; }
virtual void goSouth() { cout<<"Sorry, you can't go that way"; }
};
Map *map;
class RiverMap;
class JungleMap : public Map {
public:
void goNorth();
};
class RiverMap : public Map {
public:
void goSouth();
};
void JungleMap::goNorth() {
cout<<"You are going north towards the river.\n";
delete map;
map=new RiverMap;
}
void RiverMap::goSouth() {
cout<<"You are going south towards the jungle.\n";
delete map;
map=new JungleMap;
}
Note: here I'm just trying to say as close to your original design as possible and still have some code that might at least sort of work. I'm certainly not holding it up as an exemplary design, or even close to it (because, frankly, it's not).
What you should do is to sit down and think about the problem you are trying to solve, and make a proper design. In your case you have two "locations", and the "player" should be able to move between these locations. Starting from that we have identified two possible classes (Location and Player) and one behavior (the player can move from location to location).
With the above information, you could do something like this:
class Location
{
public:
void setNorth(Location* loc)
{
north_ = loc;
}
Location* getNorth() const
{
return north_;
}
void setSouth(Location* loc)
{
south_ = loc;
}
Location* getSouth() const
{
return south_;
}
void setDescription(const std::string& descr)
{
description_ = descr;
}
const std::string& getDescription() const
{
return description_;
}
protected:
Location() {} // Made protected to prevent direct creation of Location instances
private:
Location* north_;
Location* south_;
std::string description_;
};
class Jungle : public Location
{
public:
Jungle() : Location()
{
setDescription("You are in a jungle.");
}
};
class River : public Location
{
public:
River() : Location()
{
setDescription("You are close to a river.");
}
};
// The actual "map"
std::vector<Location*> map
void createMap()
{
map.push_back(new Jungle);
map.push_back(new River);
map[0]->setNorth(map[1]);
map[1]->setSouth(map[0]);
}
class Player
{
public:
Player(Location* initialLocation)
: currentLocation_(initialLocation)
{
std::cout << currentLocation_->getDescription() << '\n';
}
...
// Other methods and members needed for a "player"
void goNorth()
{
if (currentLocation_ && currentLocation_->getNorth())
{
currentLocation_ = currentLocation_->getNorth();
std::cout << currentLocation_->getDescription() << '\n';
}
}
void goSouth()
{
if (currentLocation_ && currentLocation_->getSouth())
{
currentLocation_ = currentLocation_->getSouth();
std::cout << currentLocation_->getDescription() << '\n';
}
}
private:
Location* currentLocation_; // The players current location
};
int main()
{
createMap(); // Create the "map"
Player player(map[0]); // Create a player and place "him" in the jungle
// Move the player around a little
player.goNorth();
player.goSouth();
}
In the code above, you have a single player object, which have a "current location". When you move the player around, you simply change the current location for that player. The current location of the player acts as the global Map variable you have.
Note: I'm not saying that this is a good design or code, just that it's simple.
However, if you're truly new to C++, you should probably start with some simpler problems, including tutorials on pointers and inheritance.
You appear to be confusing declaration with assignment.
The following line of code is called a declaration, it tells the compiler the properties and attributes of a thing.
JungleMap *Map;
After this line of code, the compiler knows that "Map" is a symbol (a name) referring to a pointer to a JungleMap.
The compiler doesn't have to do anything with a declaration, unless it would have a side effect, at which point it becomes a definition, which means that the declaration invokes a non-trivial constructor or provides an assignment:
struct Foo {};
struct Baz { Baz() { std::cout << "Baz is here\n"; } };
These are declarations - they don't create instances of objects, they describe the layout and functions for instances. At some point you have to create a concrete instance of them with a definition or a call to new.
struct Foo {};
struct Bar { Bar() { std::cout << "Bar is here\n"; } };
struct Baz {};
int main() {
int i; // no side effects, i is trivial.
char* p; // no side effects, p is a pointer (trivial) type
std::string* sp; // trivial, pointer
Foo f; // trivial
Bar b; // non-trivial, baz has a user-defined ctor that has side-effects.
Bar* bar; // trivial, unassigned pointer type.
Bar* bar2 = new Bar(); // side effects.
Bar bar(); // syntax error, "the most vexing parse"
}
In the above code, we never use "Baz" and we never declare an object of type Baz so the compiler essentially throws it away. Because so many of the variables are trivial and have no side effect, the result of compiling the above will be functionally equivalent to if we had written:
struct Foo {};
struct Bar { Bar() { std::cout << "Bar is here\n"; } };
int main() {
Bar* bar2 = new Bar(); // side effects.
Bar bar(); // syntax error, "the most vexing parse"
}
All of the rest does nothing.
C++ also allows you to re-use names as long as they are in different scopes, but this creates a new, hidden ("shadow") thing:
#include <iostream>
int main() {
int i = 1;
if (i == 1) {
float i = 3.141;
std::cout << "inner i = " << i << '\n';
}
std::cout << "outer i = " << i << '\n';
return 0;
}
The code you wrote will therefore compile, because it is declaring a new and private "Map" inside each of the go functions and then simply never using them.
Note that above I was able to declare i differently inside the inner scope than the outer.
C++ does not allow you to change the type of a variable - in the above code there are two variables called i. When we created the second i, it is a second variable called i the original variable didn't change.
In order to do what you are trying to do, you're going to need to learn about "polymorphism" and "inheritance", C++ concepts that will allow you to describe a "Room" or "Location" and then base JungleMap and RiverMap on that base definition such that you can take a pointer to the core concept, the Room, and write generic code that deals with rooms while moving the specifics of Jungle, River or BridgeMap into specialized functions. But I think that's beyond the scope of a reply here.
#include "boost/date_time/gregorian/gregorian.hpp"
int main()
{
boost::gregorian::greg_weekday dWeek(boost::date_time::Wednesday);
//Code One
// warning C4482: nonstandard extension used: enum 'boost::date_time::weekdays' used in qualified name
if (dWeek.as_enum()==boost::gregorian::greg_weekday::weekday_enum::Wednesday)
{
std::cout << "Today is Wednesday" << std::endl;
}
//class BOOST_DATE_TIME_DECL greg_weekday : public greg_weekday_rep {
//public:
// typedef boost::date_time::weekdays weekday_enum;
//Code Two
if (dWeek.as_enum()==boost::date_time::Wednesday)
{
std::cout << "Today is Wednesday" << std::endl;
}
}
Question> I have seen tons of code that use Code One to do the comparison of boost::date_time. Based on C++ standard, the usage of the enum is incorrect. I have provided a solution as Code Two.
Can someone give me quick look and see whether it real is CORRECT way to do comparison?
Thank you
EDIT: correction
use
boost::date_time::Wednesday
I didn't look at what type as_enum() returned. Fixed it, compiles & works (on MSVC2k10, Boost 1.48.0 self-built)
EDIT2: You'll find it buried away inside boost/date_time/gregorian/greg_facet.hpp.
namespace boost{
namespace gregorian{
typedef boost::date_time::weekdays weekday_enum;
}
}
Anyway the relevant part for the rest of the info is that there's a boost::date_time::weekdays::Wednesday, but we take out weekdays.
Enums are basically like:
enum foo { bar = 1, barre = 2, barred = 3 };
// Is sort-of the same as
typedef static const int foo;
foo bar = 1;
foo barre = 2;
foo barred = 3;
foo is not a namespace, nor is it a struct, or anything like that, it is more of a typename.
I know it's not exactly the same, but it may as well be for the purposes of using them. Using the weekday_enum qualifier inside a type like that is basically giving the compiler a tiny bit of garbage to parse, it's like saying:
typedef int foo;
struct S {
static foo var;
} p;
p.foo::var = 4; // Does this make sense? Nope...