Создание динамического типа данных в C ++ - PullRequest
3 голосов
/ 27 марта 2019

Я создаю переводчик определенного языка в C ++.После создания парсера, реализации разрешения области видимости и т. Д. Единственная проблема, которую я имею, - это реализация динамически типизированных переменных.

Следуя некоторым общим советам, я создал структуры VarData и VarType:

union VarData{
    int IntData;
    char CharData;
    double DoubleData;
};

enum class VarType {
    Int,
    Char,
    Double
};

и переменную структуру (она явно неполная):

struct Variable {

VarData data;

VarType type;

template<typename T>
void operator =(T val) {

    std::string name = typeid(T).name();

    if (name == "char") {
        data.CharData = val;
        type = VarType::Char;
    }
    else if (name == "int") {
        data.IntData = val;
        type = VarType::Int;
    }
    else if (name == "double") {
        data.DoubleData = val;
        type = VarType::Double;
    }

}
};

Ина самом деле это работает, например, в этом примере кода все назначенные значения правильно хранятся:

int main() {

Variable a;

a = '5';  // a.type is now VarType::Char
a = 57;   // a.type is now VarType::Int
a = 8.032;   // a.type is now VarType::Double

}

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

Variable operator + (Variable& v1, Variable& v2) {

    if (v1.type == VarType::Char && v2.type == VarType::Char)
        //return Variable of type int
    else if (v1.type == VarType::Double && v2.type == VarType::Int)
        // return Variable of type double
    else if (...)
}

Есть ли какой-либо другой (не включающий миллионы вложенных операторов if) способ сделать это?

Извините, если мой вопрос не совсем ясенЯ буду рад предоставить дополнительные объяснения.

1 Ответ

2 голосов
/ 27 марта 2019

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

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

Другим более эффективным способом было бы применение некоторых правил систематического продвижения по типу. Например, если вы хотите объединить в одной операции целое число и число с плавающей точкой, вы должны преобразовать все в число с плавающей точкой перед выполнением операции.

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

Не связано, но важно: Вы должны знать, что typeid() не является стандартизированным значением. Так что "int", "double" и т. Д. - хорошая реализация, но для других компиляторов могут использоваться другие строки. Это делает ваш код непереносимым

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...