Re: Append one enum to another?

Discussion in 'C++' started by Victor Bazarov, May 8, 2009.

  1. Peter Olcott wrote:
    > I have two enumerations, one is an exact proper subset of
    > the other, I would like to have a way to define the first
    > one in terms of the second one. Is there a simple way to do
    > this?


    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
    Victor Bazarov, May 8, 2009
    #1
    1. Advertising

  2. "Peter Olcott" <> wrote in message
    news:...
    >
    > "Victor Bazarov" <> wrote in message
    > news:gu1ii5$vkk$...
    >> Peter Olcott wrote:
    >>> I have two enumerations, one is an exact proper subset of the other, I
    >>> would like to have a way to define the first one in terms of the second
    >>> one. Is there a simple way to do this?

    >>
    >> 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?

    >
    > 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'.
    Chris M. Thomasson, May 8, 2009
    #2
    1. Advertising

  3. Peter Olcott wrote:
    > "Victor Bazarov" <> wrote in message
    > news:gu1ii5$vkk$...
    >> Peter Olcott wrote:
    >>> I have two enumerations, one is an exact proper subset of
    >>> the other, I would like to have a way to define the first
    >>> one in terms of the second one. Is there a simple way to
    >>> do this?

    >> 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?

    >
    > 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;


    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 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.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, May 8, 2009
    #3
  4. Peter Olcott wrote:
    > "Victor Bazarov" <> wrote in message
    >> [..]
    >> When I (or somebody else) ask 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.


    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.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, May 12, 2009
    #4
  5. Peter Olcott wrote:
    > 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.


    You say nothing about the way 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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, May 14, 2009
    #5
  6. Peter Olcott wrote:
    > "Victor Bazarov" <> wrote in message
    > news:guh66c$5l0$...
    >> Peter Olcott wrote:
    >>> 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.

    >> You say nothing about the way those "concepts" or enums
    >> are going
    >> to be used.

    >
    > 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.


    <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...

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, May 15, 2009
    #6
  7. "Peter Olcott" <> wrote in message
    news:...
    >
    > "Victor Bazarov" <> wrote in message
    > news:gu1ii5$vkk$...
    >> Peter Olcott wrote:
    >>> I have two enumerations, one is an exact proper subset of the other, I
    >>> would like to have a way to define the first one in terms of the second
    >>> one. Is there a simple way to do this?

    >>
    >> 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?

    >
    > 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;


    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"
    };
    Christopher Dearlove, May 15, 2009
    #7
  8. "Christopher Dearlove" <> writes:

    > "Peter Olcott" <> wrote in message
    > news:...
    >>
    >> "Victor Bazarov" <> wrote in message
    >> news:gu1ii5$vkk$...
    >>> Peter Olcott wrote:
    >>>> I have two enumerations, one is an exact proper subset of the other, I
    >>>> would like to have a way to define the first one in terms of the second
    >>>> one. Is there a simple way to do this?
    >>>
    >>> 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?

    >>
    >> 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;

    >
    > 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__
    Pascal J. Bourguignon, May 15, 2009
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. June Moore

    Append one array to another array

    June Moore, Oct 28, 2004, in forum: Java
    Replies:
    20
    Views:
    68,043
    HeidelbergMan
    Jul 6, 2007
  2. mrhicks
    Replies:
    2
    Views:
    418
    Dave Thompson
    Jun 10, 2004
  3. Replies:
    8
    Views:
    616
    John Machin
    Jul 13, 2005
  4. HYRY
    Replies:
    10
    Views:
    602
    Bruno Desthuilliers
    Sep 26, 2007
  5. Ishmael

    Append one file to another?

    Ishmael, Jun 23, 2009, in forum: C Programming
    Replies:
    5
    Views:
    1,718
    user923005
    Jun 23, 2009
Loading...

Share This Page