compilation error with enum.

Discussion in 'C++' started by subramanian, Jan 6, 2007.

  1. subramanian

    subramanian Guest

    Hello.
    Consider the following code fragment :

    enum TestEnum { val1 = 10, val2 = 100, val3 = 1000 };

    class Test {
    public :
    enum TestEnum { val1 = 1, val2 val3 };
    Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));
    ...
    private :
    int x, y;
    TestEnum a;
    static Test default_test;
    };

    Test Test::default_test(1, 2, val1);

    int main(void)
    {
    Test temp_test(1, 2, val1);
    ...
    }
    --------------------------------------------------------------

    QUESTIONS:

    1)
    I am getting compilation error for Test temp_test(1, 2, val1); val1 is
    not taken from global enum TestEnum nor the Test::val1. However in the
    static member definition,
    Test Test::default_test(1, 2, val1);
    val1 is considered to be Test::val1. Here I am not getting compilation
    error. Why is this difference, considering that both are ctors where
    val1 appears.

    2)
    In the static class member definition
    Test Test::default_test(1, 2, val1);
    val1 is taken from Test::val1. Why is not the global val1 considered ?
    subramanian, Jan 6, 2007
    #1
    1. Advertising

  2. subramanian

    Sean Fritz Guest

    subramanian wrote:

    > Hello.
    > Consider the following code fragment :
    >
    > enum TestEnum { val1 = 10, val2 = 100, val3 = 1000 };
    >
    > class Test {
    > public :
    > enum TestEnum { val1 = 1, val2 val3 };
    > Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));
    > ...
    > private :
    > int x, y;
    > TestEnum a;
    > static Test default_test;
    > };
    >
    > Test Test::default_test(1, 2, val1);
    >
    > int main(void)
    > {
    > Test temp_test(1, 2, val1);
    > ...
    > }
    > --------------------------------------------------------------
    >
    > QUESTIONS:
    >
    > 1)
    > I am getting compilation error for Test temp_test(1, 2, val1); val1 is
    > not taken from global enum TestEnum nor the Test::val1. However in the
    > static member definition,
    > Test Test::default_test(1, 2, val1);
    > val1 is considered to be Test::val1. Here I am not getting compilation
    > error. Why is this difference, considering that both are ctors where
    > val1 appears.

    Might need more information to answer this correctly (declared functions of
    Test as well as their defined form). Your code is a bit confusing, and I
    think posting the whole thing might help.

    >
    > 2)
    > In the static class member definition
    > Test Test::default_test(1, 2, val1);
    > val1 is taken from Test::val1. Why is not the global val1 considered ?

    Test::val1 has global scope, but the other val1 (which has file scope)
    overrides it. You can explicitly call the val1 you want using Test::val1,
    but it's generally a better practice to make Test::val1 private and use a
    public getter function to retrieve and and a public setter function to
    change it.
    Sean Fritz, Jan 6, 2007
    #2
    1. Advertising

  3. subramanian

    subramanian Guest

    Consider the complete code:

    #include <iostream>

    enum TestEnum { val1 = 10, val2 = 100, val3 = 1000 };

    class Test {
    public :
    enum TestEnum { val1 = 1, val2, val3 };
    Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));

    private :
    int x, y;
    TestEnum a;
    static Test default_test;
    };

    Test Test::default_test(1, 2, val1);

    Test::Test(int i, int j, TestEnum val)
    {
    x = i;
    y = j;
    a = val;

    std::cout << "x = " << x << " y = " << y << " a = " << a << '\n';
    return;
    }

    int main(void)
    {
    // Test temp_test(1, 2, val1);

    return 0;
    }

    This progam compiles without errors. When I run this program, the
    following output is generated:

    x = 1 y = 2 a = 1

    This output corresponds to the statement
    Test Test::default_test(1, 2, val1);

    Here val1 is taken from Test::val1 as can be seen from the output value
    1 (not 10). I thought val1 should be the global enum val1 = 10. What is
    the expected behaviour ?

    Now consider the following commented statement present in main:
    // Test temp_test(1, 2, val1);

    If I remove the comment, I am getting the following compilation error
    for the third argument val1. (This is in VC++ 2005 Express edition.)

    'Test::Test(int,int,Test::TestEnum)' : cannot convert parameter 3 from
    'TestEnum' to 'Test::TestEnum'

    Does it mean that the third parameter val1 is considered from the
    global TestEnum not the Test class' TestEnum ?. But in the previous
    definition of the static Test::default_test, Test::val1 is used even
    though the same ctor is used. What is the difference between these two
    ctor calls ?

    (Note: With g++ also, I am getting the same output
    x = 1 y = 2 a = 1

    and a compilation error for the commented statement when the comment is
    removed)

    Kindly clarify
    subramanian, Jan 6, 2007
    #3
  4. subramanian

    Jim Langston Guest

    "subramanian" <> wrote in message
    news:...
    > Consider the complete code:
    >
    > #include <iostream>
    >
    > enum TestEnum { val1 = 10, val2 = 100, val3 = 1000 };
    >
    > class Test {
    > public :
    > enum TestEnum { val1 = 1, val2, val3 };
    > Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));
    >
    > private :
    > int x, y;
    > TestEnum a;
    > static Test default_test;
    > };
    >
    > Test Test::default_test(1, 2, val1);
    >
    > Test::Test(int i, int j, TestEnum val)
    > {
    > x = i;
    > y = j;
    > a = val;
    >
    > std::cout << "x = " << x << " y = " << y << " a = " << a << '\n';
    > return;
    > }
    >
    > int main(void)
    > {
    > // Test temp_test(1, 2, val1);
    >
    > return 0;
    > }
    >
    > This progam compiles without errors. When I run this program, the
    > following output is generated:
    >
    > x = 1 y = 2 a = 1
    >
    > This output corresponds to the statement
    > Test Test::default_test(1, 2, val1);
    >
    > Here val1 is taken from Test::val1 as can be seen from the output value
    > 1 (not 10). I thought val1 should be the global enum val1 = 10. What is
    > the expected behaviour ?
    >
    > Now consider the following commented statement present in main:
    > // Test temp_test(1, 2, val1);
    >
    > If I remove the comment, I am getting the following compilation error
    > for the third argument val1. (This is in VC++ 2005 Express edition.)
    >
    > 'Test::Test(int,int,Test::TestEnum)' : cannot convert parameter 3 from
    > 'TestEnum' to 'Test::TestEnum'


    And that tells you exactly what the problem is. The class defintion of
    Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));
    is getting it's definition of TextEnum from the enum in the class.

    In main, however, it sees val1 as coming from the global TestEnum.

    "from TestEnum to Test::TestEnum"
    could be rephrases as:
    "from ::TestEnum to Test::TestEnum"
    with ::TestEnum being in the unnamed namespace.

    One way in man is to make it:
    Test temp_test( 1, 2, Test::TestEnum::val1 );

    The other way is to get rid of the enum definition inside of your class so
    it also uses the one n the unnamed namespace.

    > Does it mean that the third parameter val1 is considered from the
    > global TestEnum not the Test class' TestEnum ?. But in the previous
    > definition of the static Test::default_test, Test::val1 is used even
    > though the same ctor is used. What is the difference between these two
    > ctor calls ?
    >
    > (Note: With g++ also, I am getting the same output
    > x = 1 y = 2 a = 1
    >
    > and a compilation error for the commented statement when the comment is
    > removed)
    >
    > Kindly clarify
    >
    Jim Langston, Jan 6, 2007
    #4
  5. subramanian

    Sean Fritz Guest

    subramanian wrote:

    > enum TestEnum { val1 = 10, val2 = 100, val3 = 1000 };


    I'm not quite sure why you are trying to name an enum.

    >
    > class Test {
    > public :
    > enum TestEnum { val1 = 1, val2, val3 };


    Same comment as above.

    > Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));


    I see that you are defining the ctor outside the class, we don't use any
    names here. TestEnum isn't a type.
    Test( int, int, int );

    > int x, y;
    > TestEnum a;


    Again, TestEnum not a type.
    int x, y, a;

    > static Test default_test;


    This should be taken out.

    > };
    >
    > Test Test::default_test(1, 2, val1);


    Need to define ctor:

    Test::Test( int i, int j, int val )
    :x( i ) //set Test::x to i
    :y( j )
    :a( val )
    {
    cout << "x = " << x << ", y = " << y << ", a = " << a << endl;
    }

    Test default_test( 1, 2, val1 ); // this part goes in main()

    >
    > Test::Test(int i, int j, TestEnum val) // TestEnum is the name of an
    > {
    > x = i;
    > y = j;
    > a = val;
    >
    > std::cout << "x = " << x << " y = " << y << " a = " << a << '\n';
    > return;
    > }


    Remove this.

    Maybe those changes will work?
    Sean Fritz, Jan 6, 2007
    #5
  6. subramanian

    Sean Fritz Guest

    Sean Fritz wrote:

    > subramanian wrote:
    >
    >> enum TestEnum { val1 = 10, val2 = 100, val3 = 1000 };

    >
    > I'm not quite sure why you are trying to name an enum.
    >
    >>
    >> class Test {
    >> public :
    >> enum TestEnum { val1 = 1, val2, val3 };

    >
    > Same comment as above.
    >
    >> Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));

    >
    > I see that you are defining the ctor outside the class, we don't use any
    > names here. TestEnum isn't a type.
    > Test( int, int, int );
    >
    >> int x, y;
    >> TestEnum a;

    >
    > Again, TestEnum not a type.
    > int x, y, a;
    >
    >> static Test default_test;

    >
    > This should be taken out.
    >
    >> };
    >>
    >> Test Test::default_test(1, 2, val1);

    >
    > Need to define ctor:
    >
    > Test::Test( int i, int j, int val )
    > :x( i ) //set Test::x to i
    > :y( j )
    > :a( val )
    > {
    > cout << "x = " << x << ", y = " << y << ", a = " << a << endl;
    > }
    >
    > Test default_test( 1, 2, val1 ); // this part goes in main()
    >
    >>
    >> Test::Test(int i, int j, TestEnum val) // TestEnum is the name of an
    >> {
    >> x = i;
    >> y = j;
    >> a = val;
    >>
    >> std::cout << "x = " << x << " y = " << y << " a = " << a << '\n';
    >> return;
    >> }

    >
    > Remove this.
    >
    > Maybe those changes will work?


    I'm still learning too, so I may be wrong sometimes.
    Sean Fritz, Jan 6, 2007
    #6
  7. subramanian

    subramanian Guest

    I first say that I am learning C++. As part of the learning exercise I
    tried the above code.

    Part of my doubt still persists.
    I state it here.

    In the statement

    Test Test::default_test(1, 2, val1);

    val1 is taken from Test::val1. However in the statement

    Test temp_test(1, 2, val1);

    val1 is taken from the global TestEnum. In both cases, same ctor is
    called. So, I do not understand as to why in these two constructions,
    val1 of different TestEnum is included.

    Kindly clarify
    subramanian, Jan 6, 2007
    #7
  8. * Sean Fritz:
    > subramanian wrote:
    >
    >> enum TestEnum { val1 = 10, val2 = 100, val3 = 1000 };

    >
    > I'm not quite sure why you are trying to name an enum.


    The name is used to refer to the enum type later on.


    >> class Test {
    >> public :
    >> enum TestEnum { val1 = 1, val2, val3 };

    >
    > Same comment as above.
    >
    >> Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));

    >
    > I see that you are defining the ctor outside the class, we don't use any
    > names here. TestEnum isn't a type.


    TestEnum is a type.

    Hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jan 6, 2007
    #8
  9. * subramanian:
    > Hello.
    > Consider the following code fragment :
    >
    > enum TestEnum { val1 = 10, val2 = 100, val3 = 1000 };
    >
    > class Test {
    > public :
    > enum TestEnum { val1 = 1, val2 val3 };


    Missing comma in the value list (always paste actual code).


    > Test(int i = 0, int j = 0, TestEnum val = TestEnum(0));
    > ...
    > private :
    > int x, y;
    > TestEnum a;
    > static Test default_test;
    > };
    >
    > Test Test::default_test(1, 2, val1);


    This is a member definition. Identifiers are first looked up in the
    scope of the class where the member (here default_test) is declared.
    Thus 'val1' refers to Test::val1.

    The actual rules are unfortunately very complex.

    Instead of saying what I wrote above (a simplicifation that is
    necessarily not 100% correct in all cases) §3.4/12 tells you that an
    unqualified name used in the definition of a static data member of class
    T is looked up in the same way as for the definition of a T member
    function, and §3.4/8 then lists the possible places where such a name is
    looked up, namely (1) a declaration before its use in the block in which
    it is used or in an enclosing block (if the usage is in a block), (2) as
    a member of T, which is the case here, (3) ..., more stuff about nested
    classes and namespaces, yes, the details are complicated. ;-)

    For example, don't ask me about the lookup of a member function's result
    type -- is it "in" the definition wrt. name lookup, or not?

    I'd have investigate that, but generally, I just qualify names to render
    such questions moot. Which is generally a good idea anyway: explicit
    code, not code relying on implicit things. For we all use a subset of
    C++ that we're comfortable with, and must look up things outside that
    sub-language, and implicit things make this very much harder....


    > int main(void)
    > {
    > Test temp_test(1, 2, val1);


    This is not a member definition. Identifiers are therefore looked up in
    the scope of the declaration, not in the scope of the class of the thing
    being declared. The only unqualified 'val1' available here is the
    global '::val1'. Which is not implicitly convertible to Test::TestEnum.
    Which is generally a good thing, so that you know you're using the
    wrong enum type -- simply write Test::val1 to use the correct 'val1'.

    > ...
    > }
    > --------------------------------------------------------------
    >
    > QUESTIONS:
    >
    > 1)
    > I am getting compilation error for Test temp_test(1, 2, val1); val1 is
    > not taken from global enum TestEnum nor the Test::val1. However in the
    > static member definition,
    > Test Test::default_test(1, 2, val1);
    > val1 is considered to be Test::val1. Here I am not getting compilation
    > error. Why is this difference, considering that both are ctors where
    > val1 appears.


    See above.


    > 2)
    > In the static class member definition
    > Test Test::default_test(1, 2, val1);
    > val1 is taken from Test::val1. Why is not the global val1 considered ?


    See above.

    Hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jan 6, 2007
    #9
  10. subramanian

    BobR Guest

    subramanian wrote in message ...
    >I first say that I am learning C++. As part of the learning exercise I
    >tried the above code.


    What 'above code'? As Shultz said, "I see *nothing*!". <G>

    >Part of my doubt still persists. I state it here.
    >In the statement
    >
    > Test Test::default_test(1, 2, val1);


    Looks first for 'val1' *inside* the class scope, then outside the class
    (global) if not found.
    If you want the 'outside' enum:

    Test Test::default_test( 1, 2, ::val1 );
    // or: Test Test::default_test( 1, 2, TestEnum::val1 );

    >val1 is taken from Test::val1. However in the statement
    >
    >Test temp_test(1, 2, val1);


    Assume this is inside main(). So, the compiler first looks inside main()
    scope for 'val1'. It does not find it so goes looking for it at global scope.
    The compiler does not know to look in your class unless you tell it to:
    'Test::val1'.

    >
    >val1 is taken from the global TestEnum. In both cases, same ctor is
    >called. So, I do not understand as to why in these two constructions,
    >val1 of different TestEnum is included.
    >Kindly clarify
    >


    You seem to not understand 'scope'.
    I still had this example/test laying around, try it.

    #include <iostream> // #include <ostream>

    int xyz(12345); // note global scope

    int main(){
    std::cout<<" ------- "<<std::endl;
    int abc(0), bla(0), blabla(5); // normal: s/b one var per code line.
    int xyz(5); // local scope (main)
    { // scope 1
    int xyz(22); // local scope (un-named inside main)
    std::cout<<"xyz="<<xyz<<std::endl;
    } // scope 1 end
    { // scope 2
    double xyz(3.14); // local scope (un-named inside main)
    std::cout<<"xyz="<<xyz<<std::endl;
    } // scope 2 end
    std::cout<<"abc="<<abc<<" bla="<<bla
    <<" xyz="<<xyz<<std::endl;
    for( int bla(0); bla < blabla; ++bla){ // for has scope too.
    ++abc;
    std::cout << " abc=" << abc << " bla=" << bla;
    static int xyz(25); // local scope ( inside for() )
    std::cout <<" xyz="<<xyz++<<" ::xyz="
    <<( ::xyz++ )<<std::endl; // note global access
    } // for(bla)
    std::cout<<"abc="<<abc<<" bla="<<bla
    <<" xyz="<<xyz<<std::endl;
    std::cout<<" ------- "<<std::endl;
    return 0;
    } // main()

    Compile and run that, note the output (esp. the different 'xyz's).
    There are five different 'xyz' in that. Without the scoping you would break
    the one-definition rule (ODR).

    [ Just because you can, should you? Using the same name for different things
    can lead to confusion. ]
    --
    Bob R
    POVrookie
    BobR, Jan 6, 2007
    #10
    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. -

    enum within an enum

    -, Jun 12, 2005, in forum: Java
    Replies:
    6
    Views:
    519
  2. Jerminia
    Replies:
    3
    Views:
    608
    Roedy Green
    Oct 7, 2005
  3. Ernst Murnleitner

    How to enum an enum?

    Ernst Murnleitner, Nov 12, 2003, in forum: C++
    Replies:
    5
    Views:
    436
    Rolf Magnus
    Nov 13, 2003
  4. mrhicks
    Replies:
    2
    Views:
    398
    Dave Thompson
    Jun 10, 2004
  5. C__chp
    Replies:
    4
    Views:
    491
    Puppet_Sock
    Feb 15, 2008
Loading...

Share This Page