C ++: возможно ли установить тип пустого указателя, варианта-объекта или любого-объекта во время выполнения? - PullRequest
1 голос
/ 03 августа 2020

Пустотный указатель, варианты-объекты и любые-объекты удивительны, потому что они могут хранить много разных типов в одной и той же переменной. Но у меня с ними проблема, мне нужно указать их тип (создание и / или снятие ссылки с них) во время выполнения, возможно ли это?

Для большей ясности, например, насколько я знайте, что для их создания и отмены ссылок я должен сделать следующее:

void* ptr = new int(8);
variant<int, float> var = 8;
any a = 8;
...
cout << *(int*)ptr;
cout << get<int>(var);
cout << any_cast<int>(a);

Как видите, во всех случаях тип должен быть «записан в коде» (время программирования?). Было бы отлично, если бы этот тип можно было определить во время выполнения. Дайте мне пофантазировать ... если, например, мы могли бы «хранить тип» как объект, мы могли бы сделать это:

TYPE mi_tipo;
...
mi_tipo = int;   // or float, or char or any other...
...
void* ptr = new mi_tipo();
cout << *(mi_tipo*)ptr;

Что-то подобное возможно? Если нет, как бы вы это сделали? Я пытаюсь смоделировать работу компилятора, поэтому мне нужна структура, которая может хранить любые типы переменных, и поэтому мне нужен эффективный способ отменить их ссылку во время выполнения.

Ответы [ 3 ]

1 голос
/ 03 августа 2020

C ++ - язык со статической типизацией. Тип любого выражения должен быть известен во время компиляции. Хотя код времени компиляции может выполнять ограниченные формы вычисления типов и даже в определенной степени генерировать типы, все это существует только во время компиляции.

Как только вы достигнете среды выполнения, все должно быть известно. Полиморфизм Dynami c через базовые классы и virtual функции существует, но в момент создания фактического объекта вы должны знать, какой он тип. Существуют методы, которые позволяют динамически определять, какой производный класс polymorphi c следует создать, но все они в конечном итоге сводятся к набору условных операторов и жестко запрограммированному (даже если сгенерированному с помощью шаблонов) набору типов.

0 голосов
/ 03 августа 2020

Что-то подобное возможно?

За исключением using mi_tipo = int;, нет, c ++ - это язык со статической типизацией .

если нет, как бы вы это сделали?

Определитесь с интерфейсом для ваших типов, перечислите все возможные типы и напишите для них интерфейсы, чтобы скрыть реализацию.

#include <map>
#include <stdexcept>
#include <iostream>
#include <memory>
#include <sstream>

struct AtypeInterface {
    AtypeInterface() {}
    virtual ~AtypeInterface() {}
    virtual std::string format() { throw std::runtime_error("invalid"); return ""; }
};

template<typename T>
struct Atype : AtypeInterface {
    T val;
    Atype(T val) : val(val) {}
    ~Atype() {}
    std::string format() override { 
       return std::to_string(val);
    }
};
struct AtypeVoidPointer : AtypeInterface {
    void *p;
    AtypeVoidPointer(void *p) : p(p) {}
    ~AtypeVoidPointer() {}
    std::string format() override {
        // custom behavior if needed
        if (p == NULL) {
             return "och no! the pointer is null!\n";
         } else {
             std::stringstream s;
             s << p;
             return s.str();
         }
    }
};

int main() {
   std::unique_ptr<AtypeInterface> mi_typo;
   mi_typo = std::make_unique<Atype<int>>(5);
   std::cout << mi_typo->format() << '\n';
}

Такой дизайн выглядит «достаточно хорошо».

0 голосов
/ 03 августа 2020

Что-то вроде этого возможно?

Да, но вам нужно как-то самому хранить информацию о типе. В C ++ пока нет отражения, stati c или иначе.

Есть также уловки с RTTI (информация о типе времени выполнения), но я бы не рекомендовал их.

как бы вы это сделали?

Используйте тег, чтобы указать, какой тип находится внутри, например, enum class.

В противном случае используйте стандартный или сторонний решения, которые делают это за вас, например std::variant.

...