Приведение enum к int в параметре шаблона

Я определил обычай enum для удобства над определенным классом, и теперь он мешает его обработке более общими процессами.

Как я должен выполнить этот Typecast?

// 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 проблема. Ответ на Y был принят здесь, и некоторые обсуждали.
X был перемещен в Другой вопрос. Прошу прощения за неудобства.

2

Решение

Достаточно ли заменить:

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

С:

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

Поскольку это структура, вы можете получить доступ к значению. Лично я бы использовал геттеры и сеттеры, но, как представлено, это должно делать то, что вы хотите.

вперемежку

Вы можете заменить:

typedef Holder<Enum> Particular;

С:

typedef Holder<int> Particular;

Так как int может держать Enum

3

Другие решения

Вы можете добавить шаблонную функцию преобразования, которая позволит Holder<T> быть преобразованным в Holder<U> если T конвертируется в U а также T это перечисление:

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>*,

3

Я думаю, что самый простой способ заставить это работать — специализироваться Holder<Enum> так что он имеет неявное преобразование в Holder<Int>,

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

Это будет делать копии перечисления, так что это может сделать не совсем то, что вы хотите, в зависимости от того, что идет в General процессы.

1

Проблема в том, что static_cast не предназначен для наведения указателей разных типов. Я предлагаю вам использовать reinterpret_cast, это должно сделать работу. Кроме того, вы не можете создать экземпляр объекта типа IntGeneral с указателем.

0

Есть несколько изменений, которые вы можете сделать:

  1. Добавьте родительский тип в ‘Holder’, который может ссылаться как на общий, так и на особый типы.
  2. Определить конструктор для держателя, который получает T
  3. Определите конструктор для общего, который получает тип адреса Holder
  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;
    }
    

надеюсь, это то, что вы искали

0
По вопросам рекламы [email protected]