模板类中的枚举

Jix*_*xxy 3 c++ enums templates

假设我有一个类Class,它有一个关联的枚举成员Enum。枚举仅在此类的上下文中才有意义,因此它是在其中指定的。Class::Enum::Something然后你就可以从课堂外打电话,这很好。

class Class
{
   public:
      enum class Enum : uchar
      {
          Something
      }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果类Class是模板化的,则不能执行Class::Enum::Something,但必须执行Class<T>::Enum::Something(或者Class<>::Enum::Something如果T有某种默认类型)。

template <typename T = double>
class Class
{
   public:
      enum class Enum : uchar
      {
          Something
      }
}
Run Code Online (Sandbox Code Playgroud)

所有 s 都必须Enum相同T,因为它只是一个简单的枚举,但T无论如何都必须指定always。

我的问题是 - 有没有一种聪明的方法来避免这种情况?

dfr*_*fri 5

必须了解的是,对于不同的专业化,包装的枚举类型是不同的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>);  // !!!
Run Code Online (Sandbox Code Playgroud)

看起来您希望它实际上是相同的类型,在这种情况下,您可以将其分解为一个单独的类,并使用私有实现继承通过类模板专业化来公开它:

#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
Run Code Online (Sandbox Code Playgroud)

但是,如果您打算提供此枚举作为各种类模板专业化的成员(上面的别名声明),则您将需要限定您引用的专业化。

S<>::E;
S<int>::E;
Run Code Online (Sandbox Code Playgroud)

您似乎想要解决的根本问题是范围界定,在这种情况下,您可以使用名称空间而不是类来包装关联的枚举:

namespace my_lib {

template <typename T = double>
struct S {};

enum class E : int { a };

}  // namespace my_lib
Run Code Online (Sandbox Code Playgroud)