1

Basically here's what my "ideal" code would look like, if it were legal:

template<typename ClassName>
class Base{
     ClassName::units_type units;
public:
     Base(ClassName::units_type Units) : units(Units){};
     void SomeFunc(ClassName::units_type Units);
};

class Derived : public Base<Derived>{
public:
     enum units_type{
          meters,
          feet
     };
     using Base::Base;
};

What I really need is to be able to call it like this:

Derived d = Derived(Derived::meters);
d.SomeFunc(Derived::feet);

i.e. I need the units enum to be scoped to the derived class, and the derived class only - but also be available as a datatype in the base class.

Of course, this doesn't work.

There is a workaround in c++20, but I am looking for a c++17 solution. In c++20 I can write:

template<typename ClassName, typename units_type>
class Base{
     units_type units;
public:
     Base(units_type Units) : units(Units){};
     void SomeFunc(units_type Units){};
};

enum class DerivedUnits{
     meters,
     feet
};

class Derived : public Base<Derived, DerivedUnits>{
public:
     using enum DerivedUnits;
     using Base::Base;
};

This works great, and I can call

Derived d = Derived(Derived::meters);
d.SomeFunc(Derived::feet);

just like I want, and the world is a happy place. Is there a way - any way - to accomplish this same end-goal in C++17?

Thanks, Farley

lequinne
  • 118
  • 8

1 Answers1

2

The only part of your "workaround" solution that requires C++20 is using enum. You can easily avoid it like this:

template<typename ClassName, typename units_type>
class Base{
     units_type units;
public:
     Base(units_type Units) : units(Units){};
     void SomeFunc(units_type Units){};
};

enum class DerivedUnitsImpl{
     meters,
     feet
};

class Derived : public Base<Derived, DerivedUnitsImpl>{
public:
     using DerivedUnits = DerivedUnitsImpl;
     using Base::Base;
};
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • This seems to require me to add an extra scope when I call: Derived d = Derived(Derived::DerivedUnits::meters); I want to be able to call Derived(Derived::meters) – lequinne Mar 19 '23 at 17:43