Как преобразовать каждый вариантный тип с помощью шаблона Variadi c - PullRequest
1 голос
/ 16 июня 2020

Что я хочу сделать, так это привести каждый аргумент VariantType (объединение различных типов) к его типу перед вызовом какой-либо функции из разделяемой библиотеки. то, что я делаю до сих пор, находится внизу. это всего лишь 3 разных типа и 2 аргумента, и для этого требуется много строк. но я хочу добиться этого с помощью варианта номера аргумента с 7 различными типами. это должно что-то делать с вариационным шаблоном c (другой соответствующий вопрос: Кортеж шаблона - вызов функции для каждого элемента ). или если вы знаете способ получше, дайте мне знать.


template<typename... T>
int call(const char* func_name, T... args) {
    // this will call func_name(args...) somehow from a dll binary.
    // If you need the implementation : https://hastebin.com/ocoyaniruj.cpp
}

int main(int argc, char** argv) {

    const char* func_name = "func_name";
    VariantType arg1 = "hello world!";
    VariantType arg2 = 3.14;

    if (arg1.get_type() == VariantType::INT) {
        if (arg2.get_type() == VariantType::INT) {
            call(func_name, (int)arg1, (int)arg2);
        } else if (arg2.get_type() == VariantType::FLOAT){
            call(func_name, (int)arg1, (float)arg2);
        } else if (arg1.get_type() == VariantType::STRING){
            call(func_name, (int)arg1, arg2.c_str());
        }

    } else if (arg1.get_type() == VariantType::FLOAT){
        if (arg2.get_type() == VariantType::INT) {
            call(func_name, (float)arg1, (int)arg2);
        } else if (arg2.get_type() == VariantType::FLOAT){
            call(func_name, (float)arg1, (float)arg2);
        } else if (arg1.get_type() == VariantType::STRING){
            call(func_name, (float)arg1, arg2.c_str());
        }

    } else if (arg1.get_type() == VariantType::STRING){
        if (arg2.get_type() == VariantType::INT) {
            call(func_name, arg1.c_str(), (int)arg2);
        } else if (arg2.get_type() == VariantType::FLOAT){
            call(func_name, arg1.c_str(), (float)arg2);
        } else if (arg1.get_type() == VariantType::STRING){
            call(func_name, arg1.c_str(), arg2.c_str());
        }
    }
    return 0;
}

Ответы [ 2 ]

3 голосов
/ 16 июня 2020

У вас запутанный и очень частичный механизм отражения во время выполнения. Я уверен, что вам очень больно с этим материалом ... поэтому в первую очередь следует подумать:

  • Вам это действительно нужно? Если вы можете избежать этого и придерживаться рефлексии во время компиляции, это облегчит вам жизнь; или
  • C ++ - тот язык, который вы хотите использовать? Если вы только начинаете свой проект программирования и этот вид полиморфизма времени выполнения критичен для вас, возможно, другой язык (например, интерпретируемый язык?) Может быть более подходящим.

Наличие сказал, что - во многих случаях вы можете быть удовлетворены собственным типом варианта C ++: std::variant, представленным в C ++ 17 вместе с std::visit, и шаблонным посетителем (как в этот вопрос - но с двумя шаблонами).

Вот как это будет выглядеть:

#include <variant>
#include <iostream>
#include <string>

int main() {
    using variant_type = std::variant<int, float, std::string>;
    variant_type v1{"hello world!"};
    variant_type v2{3.14f};

    std::visit([](auto&& x, auto&& y) { 
        // I used this as a stub:
        //
        //   std::cout << x << " , " << y << '\n';
        //
        // but you want:
        call(func_name, x, y);
    }, v1, v2);
}

GodBolt

Но есть одно предостережение - это не извлечет c_str() из ваших строк. Если вы хотите сделать это, вы можете сделать одно из двух:

  1. Сохраните const char* в варианте для начала.
  2. вместо передачи x и y, у вас может быть шаблонная функция-преобразователь, которая обычно ничего не делает, но применяет .c_str() для ссылок на константные строки.

но мне не очень нравится второй подход.

0 голосов
/ 17 июня 2020

Наконец-то я нашел простой способ привести каждый аргумент с помощью шаблона c с вариациями (вроде изобретать колесо std::visit)

...