Accessing an enum value in a nested templated class in C++03
Asked Answered
H

2

5

I have the unfortunate task in 2024 of adding some code to a codebase that needs to be used in a C++03 setting - where unfortunately the original class myclass can't be changed.

I've gotten stuck on something simple which is accessing enum values from an enum that is defined in a nested class.

#include <cstdio>

namespace ns
{
   template <typename T>
   class myclass {
   public:
      enum etype {
         e_option1,
         e_option2,
         e_option3,
         e_option4
      };
   };
}

int main() {
   typedef typename ns::myclass<int> mc_t;
   mc_t::etype et = mc_t::etype::e_option2;

   switch(et) {
      case mc_t::etype::e_option1 : printf("option1\n"); break;
      case mc_t::etype::e_option2 : printf("option2\n"); break;
      case mc_t::etype::e_option3 : printf("option3\n"); break;
      case mc_t::etype::e_option4 : printf("option4\n"); break;
   }

   return 0;
}

https://godbolt.org/z/KeK7M54Wb

<source>: In function 'int main()':
<source>:20:27: error: 'ns::mc_t::etype' is not a class or namespace
   20 |    mc_t::etype et = mc_t::etype::e_option2;
      |                           ^~~~~
<source>:23:18: error: 'ns::mc_t::etype' is not a class or namespace
   23 |       case mc_t::etype::e_option1 : printf("option1\n"); break;
      |                  ^~~~~
<source>:24:18: error: 'ns::mc_t::etype' is not a class or namespace
   24 |       case mc_t::etype::e_option2 : printf("option2\n"); break;
      |                  ^~~~~
<source>:25:18: error: 'ns::mc_t::etype' is not a class or namespace
   25 |       case mc_t::etype::e_option3 : printf("option3\n"); break;
      |                  ^~~~~
<source>:26:18: error: 'ns::mc_t::etype' is not a class or namespace
   26 |       case mc_t::etype::e_option4 : printf("option4\n"); break;
      |                  ^~~~~
Compiler returned: 1
Hanshaw answered 11/9, 2024 at 9:44 Comment(3)
You don't need the extra ::etype when accessing enumerators. Just change it to mc_t::etype et = mc_t::e_option2;. Working demoDaniel
C++03 didn't allow qualifying an enumerator by the enum type, that was only added in C++11 (consistency between scoped and unscoped enums).Intonate
I think the main point for enum-in-class idiom was to provide a namespace when language didn't support it. So by convention the class should have the name you want to use when referring to enumerators.Colwell
D
6

You don't need the extra ::etype when accessing the enumerators in your example of unscoped enumeration as they are already visible in the enclosing scope(which is the class scope here).

So the modified working code looks like:

int main()
{
   typedef typename ns::myclass<int> mc_t;
//-----------------------v------------->no need to use `etype` here.
   mc_t::etype et = mc_t::e_option2;

   switch(et) {
//---------------v--------------------------------------->no need to use etype here
      case mc_t::e_option1 : printf("option1\n"); break;
      case mc_t::e_option2 : printf("option2\n"); break;
      case mc_t::e_option3 : printf("option3\n"); break;
      case mc_t::e_option4 : printf("option4\n"); break;
   }

   return 0;
}

Working demo

Daniel answered 11/9, 2024 at 9:53 Comment(0)
C
3

You can access the enum values using just the class name, without using the enum name. Hence, instead of mc_t::etype::e_option2, you can access the value as just mc_t::e_option2.

I would assume this is because its not an enum class, so the values are accessible directly from the parent scope.

Celadon answered 11/9, 2024 at 9:53 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.