приведение типов между экземплярами класса шаблона - PullRequest
1 голос
/ 15 июня 2019

Я сейчас экспериментирую с приведением типов в стиле c ++.Для этого я создал шаблон класса pClass, который берет некоторый элемент типа T и печатает его.

Теперь я хотел бы (например) преобразовать экземпляр типа pClass<char> в pClass<int>.Тем не менее, не мои попытки приведения типов, похоже, работают как положено.

Я уже обнаружил, что dynamic_cast используется для преобразования во время выполнения и при работе с виртуальными функциями / полиморфными классами, что здесь не так.static_cast используется для преобразования во время компиляции.Итак, в моем случае static_cast должен быть правильным выбором, я думаю?

В некоторых темах здесь, на stackoverflow, были похожие вопросы, но только при обработке нескольких классов с некоторым наследованием между ними.К сожалению, я не мог связать их с моей проблемой (например, C ++ Приведение между вызовами шаблона ).

#include <iostream>

template <typename T>
class pClass {
    public:
    T value;
    pClass(T value) {
        this->value = value;
        std::cout << value << std::endl;
    }
    virtual ~pClass() {}
};

int main() {
    pClass<int> pInt(5);
    pClass<char> pChar('a');
    pClass<float> pFloat(4.2f);

    // pClass<int> pInt2 = static_cast<pClass<int>&>(pChar); //  gives invalid type conversation
    // pClass<int>& pInt3 = dynamic_cast<pClass<int>&>(pChar); // warning: dynamic_cast of ‘pClass<char> pChar’ to ‘class pClass<int>&’ can never succeed
    // pClass<int> pInt4 = reinterpret_cast<pClass<int>&>(pChar); // works, but does not print anything
    // std::cout << pInt2.value << std::endl; // prints 3277 or even 327777 exept of 97, which is the expected ASCII representation
}

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

Большое спасибо!

1 Ответ

5 голосов
/ 15 июня 2019

Хотя типы взяты из одного и того же шаблона, они абсолютно не связаны. Вы не можете просто приводить между ними, как компилятор может знать, что вы подразумеваете под приведением? Из-за специализации шаблонов pClass<char> может даже не содержать char, который может быть приведен к int.

Решение состоит в том, чтобы написать значение приведения , используя cast оператор преобразования:

template <typename T>
class pClass {
    public:
    T value;
    pClass(T value) {
        this->value = value;
        std::cout << value << std::endl;
    }
    virtual ~pClass() {}

    template<typename U>
    operator pClass<U>(){
        return pClass<U>(static_cast<U>(this->value));
    }
};

Приведенный выше метод позволяет приводить между любыми двумя значениями pClass<T> и pClass<U> путем приведения сохраненного значения. Это сделает следующий код скомпилированным:

pClass<int> pInt{1};
pClass<float> pfloat{pInt};

Где вторая строка - конструктор копирования pClass<float>::pClass<float>(const pClass<float>&);, который использует неявное приведение для преобразования pInt в pClass<float> тип.

Я бы рекомендовал сделать оператор преобразования явным:

template<typename U> explicit operator pClass<U>()

Это запрещает неявное преобразование, описанное выше, но все же допускает явное приведение:

pClass<float> pfloat{static_cast<pClass<float>>(pInt)};
...