在模板参数中将枚举转换为 int

Casting enum to int in a template parameter

为了方便特定的 class,我已经定义了一个自定义 enum,现在它妨碍了更通用的进程对其进行处理。

我应该如何执行此类型转换?

// A templated value holder:
template <typename T>
struct Holder {
    T _value;
};

// A more general process..
template <typename T>
struct General {
    Holder<T> *holder;
};
// ..over integral types:
struct IntGeneral : General<int> {};
// Here is something interesting: I can tell that this process will work on
// any enum type. But I've found no way to make this explicit.

// Convenience for a particular case
typedef enum {One, Two, Three} Enum;
typedef Holder<Enum> Particular;


int main() { 

    Particular* a( new Particular { One } );
    IntGeneral ig { static_cast<Holder<int>*>(a) }; // compiler grumbles

    return EXIT_SUCCESS;
}

这是我得到的:

error: invalid static_cast from type ‘Particular* {aka Holder<Enum>*}’ to type ‘Holder<int>*’

有什么方法可以保持方便 Enum 并编译此代码?


编辑:原来是 XY problem。此处接受了对 Y 的回答,并讨论了几个。 X 已移至 .

我认为使它工作的最简单方法是专门化 Holder<Enum> 以便它隐式转换为 Holder<Int>.

template<>
struct Holder<Enum> {
  Enum _value;
  operator Holder<Int>() const { return { _value }; }
};

虽然这将制作枚举的副本,因此这可能不会完全按照您的要求执行,具体取决于 General 进程中发生的事情。

如果 T 可转换为 UT 可转换为 Holder<T>,则您可以添加一个模板转换函数,允许将 Holder<T> 转换为 Holder<U>一个枚举:

template <typename T>
struct Holder {
    T _value;

    template <typename U,
              typename = std::enable_if_t<
                std::is_convertible<T, U>::value && 
                std::is_enum<T>::value 
              >>
    operator Holder<U>() const {
        return {_value};
    }
};

可能 只需 可转换性检查就足够了,具体取决于您的用例。

这会让你写:

Holder<int> i = Holder<Enum>{One};

但它不会让您将指针转换为强制转换。您必须分配一个全新的 Holder<int>* 来存储 Holder<Enum>*

问题是 static_cast 不适用于转换不同类型的指针。我建议您使用 reinterpret_cast,它应该可以完成工作。此外,您不能使用指针实例化 IntGeneral 类型的对象。

是否足以替换:

IntGeneral ig { static_cast<Holder<int>*>(a) }; // compiler grumbles

有:

IntGeneral ig { new Holder<int>{a->_value} };

因为是结构体,所以可以访问值。就我个人而言,我会使用 getter 和 setter,但正如所展示的那样,这应该可以满足您的需求。

交替

您可以替换:

typedef Holder<Enum> Particular;

有:

typedef Holder<int> Particular;

因为 int 可以容纳 Enum

您可以进行一些更改:

  1. 向 'Holder' 添加可以引用通用类型和特定类型的父类型。
  2. 为接收 T 的 Holder 定义一个构造函数
  3. 为接收 Holder 地址类型的 General 定义一个构造函数
  4. 对于 IntGeneral 的初始化列表(这是一个奇怪的名字,因为它不是通用的,但我明白了)用 "Holder*" 地址启动。

    struct HolderBase {};
    
    template <typename T>
    struct Holder : HolderBase{
         Holder(T value){ _value = value; }
         T _value;
    };
    
    template <typename T>
    struct General {
        General(Holder<T>* h){ holder = h; }
        Holder<T>* holder;
    };
    
    struct IntGeneral : General<int> {
        IntGeneral(Holder<int>* holder) : General<int>(holder){}
    };
    
    typedef enum { One, Two, Three } Enum;
    typedef Holder<Enum> Particular;
    
    
    int main() {
    
       HolderBase* a(new Particular{ One });
       IntGeneral ig{ static_cast<Holder<int>*>(a) };
    
       return 0;
    }
    

希望这就是您要找的东西