#c
#c
Вопрос:
#include <iostream>
template <typename T>
class Item {
public:
T item;
void* ptr = nullptr;
Item(T var): item(var) {}
unknown next(){
if ((unknown*)ptr != nullptr){
std::cout<<"It is not a null pointer!"<<std::endl;
return (unkown*)ptr
}else{
std::cout<<"It is a null pointer..."<<std::endl;
return NULL
}
}
template <typename temp>
void pass(temp *var){
ptr = var;
}
};
int main() {
Item<int> i(100);
Item<float> n(200.0);
i.pass(amp;n);
i.next();
}
Моя проблема в том, чтобы «запомнить» тип T
, чтобы я мог заменить unknown
.
Мне нужен void*
указатель, указывающий на неизвестный тип, и мне нужно ввести приведение к нужному типу, чтобы получить то, что я в нем сохранил. При Item
создании ничего не было зарегистрировано (ничего не должно быть зарегистрировано).
Если вы, ребята, каким-то образом знаете, как это сделать, возможно ли также изменить тип «запоминается» во время компиляции?
Комментарии:
1. Я предполагаю, что вы хотите заменить
unknown
наtemp
, а не наT
? Это невозможно.2. Что мешает вам использовать
T
во всех местахunknown
? После исправления нескольких ошибок (пропущенных;
и*
) ваш код затем компилируется и выводит «Это не нулевой указатель!». Я не вижу вашей проблемы, если вы не пытаетесь использоватьT
извне класса. И даже тогда есть очевидное решение.3. В
void *
коде C следует использовать только для взаимодействия с API библиотеки C. Никогда не нужно использоватьvoid *
в хорошо разработанном коде C для чего-либо.
Ответ №1:
pass
поскольку шаблон может принимать бесконечное количество типов, в то время как возвращаемый тип next
фиксирован к одному типу. Вы запрашиваете способ обработки всех типов как одного типа, и, к сожалению void*
, это единственный способ; вы не можете восстановить тип, используемый pass
в.
Я не уверен на 100% во всех ваших вариантах использования этого класса, поэтому я опишу несколько методов удаления типов, которые вам следует изучить:
-
Рассмотрите возможность использования a
std::variant
и возложите ответственность за то, что делать с содержащимся типом, на посетителя, определенного пользователем. например,Item<int, double>
хранит avariant<int, double>
-
В качестве альтернативы, используйте a
std::any
и возложите бремя восстановления информации о типе на вызывающего. -
В качестве альтернативы можно принудительно удалить тип с помощью полиморфизма; вместо
void*
этого собственный указатель на базовый класс. -
Другим подходом к стиранию типов является подход Sean Parent «полиморфизм во время выполнения«, в котором пользователь предоставляет реализацию требуемого поведения в виде функции, которую можно обнаружить с помощью поиска, зависящего от аргумента. С помощью полиморфизма только для внутреннего использования вы можете вызвать соответствующую функцию для содержащегося указателя (не слишком отличающуюся от того, как
std::function
это реализовано).