Simple? Not sure.
enum A { a, b, c, d };
enum A_extended { ae = a, be = b, ce = c, de = d, ee, fe };
The problem with this, of course, is that if you edit 'A', then you will
have to manually edit 'A_extended'. Since they are not "related", there
is no "inheriting" of values. You *could* wrap them both in classes and
then derive the A_extended wrapper from the A wrapper... That would
bring all A wrapper enums into A_extended wrapper's scope. What exactly
are you trying to accomplish?
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
enum A {a, b, c, d};
enum B = A + {e, f, g, h};
I want to have the compiler keep these two in sync for me so
that any changes to A will automatically be incorporated
into B;
I guess you can try something like this:
___________________________________________________________________
#include <cstdio>
struct enum_a {
enum constant {
a, b, c, d,
end_of_enum_a = d
};
};
struct enum_b : public enum_a {
enum constant {
e = end_of_enum_a + 1,
f, g, h
};
};
int main() {
std::printf("enum_a: a(%d), b(%d), c(%d), d(%d)\n",
enum_b::a, enum_b::b, enum_b::c, enum_b::d);
std::printf("enum_b: e(%d), f(%d), g(%d), h(%d)\n",
enum_b::e, enum_b::f, enum_b::g, enum_b::h);
return 0;
}
___________________________________________________________________
If you change `enum_a' you would need to update `enum_a::end_of_enum_a'
accordingly. This is assuming that you want to keep a monotonically
increasing value that spills from `enum_a' into `enum_b'.
Well, it doesn't make them the same type, so you can't reuse 'a' where
'B' is expected. Chris published a solution where those are wrapped,
like I suggested, but that doesn't make them the same type either. What
is the point of having those enums? Are the sequential numbers with
symbolic representation all you need? How would you use those enums?
What is the reason, the goal, to have one "extend" the other?
When I (or somebody else) ask[s] what you're trying to accomplish,
please don't answer in terms of some impossible solution that you've
thought up. Explain the problem you're trying to solve.
I need to create two sets of enumerated constants where one
is always a proper subset of the other. I am aiming to
minimize errors with ongoing code maintenance by trying to
find a way such that the superset inherits the subset. It
looks like simply having to keep these two manually in sync
is the only reasonably easy way to go.
You said that already. What problem does that solve? *Why* do they
need to be *different* sets of constants? *Why* should one be a subset
of the other? What problem does that solve for you? Could it be that
there is a different solution to what you're trying to accomplish with
the two enumerations?
Don't get me wrong; I don't really care to know your secret if the
problem you're solving is secret. I am trying to get you to explain the
actual problem because you seem to be hung up on the *solution* that
does not necessarily work, or, rather brings forth other problems (like
the need to maintain the dependency)...
> I am aiming to
> minimize errors with ongoing code maintenance by trying to
> find a way such that the superset inherits the subset.
Isn't everybody [aiming to minimize errors]? But you're limiting your
options by not looking (and not letting us look by not explaining the
problem) at any other possible solution.
> It
> looks like simply having to keep these two manually in sync
> is the only reasonably easy way to go.
Fine. The law of diminishing returns says that one has to stop looking
at some point. Just make sure to place enough comment in your code to
explain your rationale and possibly encourage revisiting your approach,
for anybody who decides to do so when maintaining your code down the road.
You could use the old "x macros" technique to keep them in sync.
REH
I have two sets of concepts whereas one set of concepts
naturally forms a mathematical proper subset of the other. I
must represent these concepts in code, and enums are the
most efficient and concise.
In the specific case I am creating a greatly simplified C++
interpreter and the subset concepts are data types and the
superset concepts are SymbolTable types, the SymbolTable has
some of its own specialized types such as Function
ProtoType.
You say nothing about the way[s] those "concepts" or enums are going
to be used. Perhaps wrapping those in a class (or in two classes) is
what you need (or have already done). Keep in mind that inheritance is
a tricky thing.
In your second post you mentioned the form 'enum B = A + { blah };'.
What would it give you? What do you mean by "automatically
incorporated"? And what about Chris' suggestion with the
'end_of_enum_a' value used in 'B' to start the enumeration? Also, you
didn't at all respond to my comment that those enums are still two
different types.
Could it be that you simply need a set of numbers? What if you use an
array of int and a bunch of [named] references to its elements? You can
then use 'sizeof' to generate the second, bigger, array.
I can understand efficiency, I can understand conciseness. And it seems
that you're after ease of maintaining those as well. I don't know the
problems you're facing in the maintenance phase, but perhaps if you post
the code (before and after) and your maintenance concerns, something can
be proposed, like a couple of compile-time assertions and plenty of code
comments...
> In the specific case I am creating a greatly simplified C++
> interpreter and the subset concepts are data types and the superset
> concepts are SymbolTable types, the SymbolTable has some of its own
> specialized types such as Function ProtoType.
V
You have to read the whole post, this is already listed
below:
In the specific case I am creating a greatly simplified C++
interpreter and the subset concepts are data types and the
superset
concepts are SymbolTable types, the SymbolTable has some of
its own
specialized types such as Function ProtoType.
The enums will be used in switch statements.
<sigh> Why do you presume I didn't read the post? How do you design
your classes? Do you pick a language element, like "a virtual function"
and build your program around it? Like here, you just say, "Today I'll
use enums, they go nicely with a switch statement". Is that all? No
interface? No messaging? No states?
Why do you have classes? Take SymbolTable class, why does it need those
enums? Are you implementing some kind of dispatch mechanism with those?
Why not with indices or function pointers? Does the "simplified" in
your description of what you're programming relate to "C++" or to
"interpreter"?
> The enums will be used in switch statements.
Well, duh.
There are other things that can be use in switch statements, you know,
like characters or other integral values. Dispatch can also be done
using virtual functions and pointers to member functions... Arrays
(vectors) are much easier to append to each other than enums...
The cure is almost certainly worse than the disease, and I don't
think I'll ever be doing it, but ...
In a.h
a,b,c,d
In b.h
e,f,g,h
In ab.h
enum A {
#include "a.h"
};
enum B {
#include "a.h"
,
#include "b.h"
};
Assuming an operator to define a enum type A:
(defenum A
a b c d)
you can trivially do what you want as:
(eval-when (:compile-toplevel :load-toplevel :execute)
(defparameter *enum-constants* (make-hash-table)))
(defmacro define-enumeration (name super-enums &rest constants)
`(defenum ,name
,@(setf (gethash name *enum-constants*)
(remove-duplicates
(append constants
(mapcan (lambda (enum) (copy-list (gethash enum *enum-constants*)))
super-enums))))))
C/USER[13]> (define-enumeration a () a b c d)
A
C/USER[14]> (define-enumeration b (a) e f g h)
B
C/USER[15]> (typep 'b 'a)
T
C/USER[16]> (typep 'e 'a)
NIL
C/USER[17]> (typep 'b 'b)
T
C/USER[18]> (typep 'e 'b)
T
C/USER[19]>
Ah yes, it's not C++. But it's hardly my fault if you keep needing
features not present in C++ but in Lisp...
Remember as soon as you want the compiler to do something for you, you
actually need Lisp: Lisp has macros, which are compiler hooks allowing
you to program the compiler to let it do what you need it to do.
--
__Pascal Bourguignon__