Let's say I have a class Class
, which has an associated enum member Enum
. The enum only makes sense in the context of this class, and therefore it is specified inside it. Then you can just call Class::Enum::Something
from outside of the class, which is fine.
class Class
{
public:
enum class Enum : uchar
{
Something
}
}
However, if the class Class
is templated, you cannot do Class::Enum::Something
, but you have to Class<T>::Enum::Something
(or Class<>::Enum::Something
if T
has some default type).
template <typename T = double>
class Class
{
public:
enum class Enum : uchar
{
Something
}
}
The Enum
has to be the same for all T
s, since it's just a simple enum, but the T
always has to be specified anyway.
My question is - is there a clever way of avoiding this?
CodePudding user response:
It is essential to understand that the wrapped enum type is a different type for different specializations of Class
.
#include <type_traits>
template <typename T = double>
struct S
{
enum class E : int { a };
};
static_assert(!std::is_same_v<S<>::E, S<int>::E>); // !!!
It seems like you want this to actually be the same type, in which case you could break it out into a separate class and use private implementation inheritance to expose it via the class template specializations:
#include <type_traits>
namespace detail {
struct Base {
enum class E : int { a };
};
} // namespace detail;
template <typename T = double>
struct S : private detail::Base
{
using Base::E;
};
static_assert(std::is_same_v<S<>::E, S<int>::E>); // OK
However if you are set on supplying this enum as a member (alias declaration above) of the various class template specializations, you will need to qualify which specialization you refer to.
S<>::E;
S<int>::E;
The root problem you seem to want to solve is scoping, in which case you may use a namespace instead of class to wrap the associated enum:
namespace my_lib {
template <typename T = double>
struct S {};
enum class E : int { a };
} // namespace my_lib
CodePudding user response:
Often it is more convenient to move everything that does not depend on the tempalte argument to a non-template base class:
#include <iostream>
class Base {
public:
enum class Enum
{
Something
};
};
template <typename T = double>
class Class : public Base
{
};
int main() {
std::cout << (Class<>::Enum::Something == Class<int>::Enum::Something);
}