简体   繁体   English

如何使用可变参数模板转换每种变体类型

[英]How to cast each variant type with variadic template

What I want to do is to cast each "VariantType" (union of different types) argument to it's type before calling some function from a shared library.我想要做的是在从共享库调用一些 function 之前将每个“VariantType”(不同类型的联合)参数转换为它的类型。 what I'm doing so far now is down below.到目前为止,我正在做的事情在下面。 it's just 3 different types and 2 arguments and it takes a lot lines.它只有 3 种不同的类型和 2 个 arguments 并且需要很多行。 but I want to achieve this with variant number of argument with 7 different types.但我想用 7 种不同类型的变体参数来实现这一点。 this has to do something with variadic template( another relevant question: Template tuple - calling a function on each element ).这与可变参数模板有关(另一个相关问题: 模板元组 - 在每个元素上调用 function )。 or if you know some better way let me know.或者,如果您知道更好的方法,请告诉我。


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;
}

You have a messy, and very partial, runtime reflection mechanism.你有一个混乱的、非常部分的运行时反射机制。 I'm sure you're feeling a lot of pain with this stuff... so the first things to consider would be:我敢肯定你对这些东西感到很痛苦......所以首先要考虑的是:

  • Do you really need this?你真的需要这个吗? If you can avoid it and stick to compile-time reflection, that would make life easier for you;如果您可以避免它并坚持编译时反射,那将使您的生活更轻松; or或者
  • Is C++ the language you want to be using? C++ 是您要使用的语言吗? If you're just getting started with your programming project, and this kind of run-time polymorphism is critical for you, perhaps another language (eg an interpreted language?) might be more appropriate.如果您刚刚开始您的编程项目,并且这种运行时多态性对您来说至关重要,那么也许另一种语言(例如解释语言?)可能更合适。

Having said that - you could, in many cases, be satisfied with C++'s own variant type: std::variant introduced in C++17, together with std::visit , and a templated visitor (as in this question - but with two templates).话虽如此 - 在许多情况下,您可以对 C++ 自己的变体类型感到满意:在 C++17 中引入的std::variant以及std::visit和一个模板化的访问者(如在这个问题中 - 但有两个模板)。

Here's what this would look like:这是它的样子:

#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神螺栓

There is one caveat, though - this won't extract the c_str() from your strings.但是,有一个警告 - 这不会从您的字符串中提取c_str() If you want to also do that, you can do one of two things:如果你也想这样做,你可以做以下两件事之一:

  1. Store a const char* in the variant to begin with.在变体中存储一个const char*开始。
  2. instead of passing x and y , you can have a templated transformer function, which does nothing usually, but applies .c_str() for const string references.除了传递xy之外,您还可以使用模板化转换器 function,它通常什么都不做,但将.c_str()应用于 const 字符串引用。

but I don't really like the second approach.但我不太喜欢第二种方法。

I've finally found the simple way to cast each argument with a variadic template (kinda reinvent the wheel std::visit ).我终于找到了使用可变参数模板强制转换每个参数的简单方法(有点重新发明轮子std::visit )。

template<typename... Targs>
void visit(const char* func_name, int visiting_arg, VariantType front, Targs... p_args) {

    if (visiting_arg == 0) {
        call(func_name, p_args...);
        return;
    }

    if (front.get_type() == VariantType::INT) {
        visit(func_name, visiting_arg-1, p_args..., (int)front);

    } else if (front.get_type() == VariantType::FLOAT) {
        visit(func_name, visiting_arg - 1, p_args..., (float)front);

    } else if (front.get_type() == VariantType::STRING) {
        visit(func_name, visiting_arg - 1, p_args..., front.c_str());

    }

}

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

    const char* func_name = "func_name";
    int argcount = 3;

    VariantType s = "Hello world!";
    VariantType f = 3.14;
    VariantType i = 42;

    visit(func_name, argcount, s, f, i, VariantType("--placeholder--"));

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将variadic模板类型转换为void,预期&#39;)&#39;之前 - Cast variadic template type to void, expected ')' before 如何获取传递给可变参数模板function的每个容器的元素类型 - How to get the element type of each container passed to variadic template function 如何使用折叠表达式实例化可变参数模板函数中的每个类型? - How to use fold expression to instantiate each type in a variadic template function? 将每个类型包装在模板化类中的可变参数模板中 - Wrapping each type in a variadic template in a templated class 对可变参数模板类型列表的每种类型进行操作的函数 - Function operating on each type of a variadic template typelist 嵌套 class 的模板模板参数的可变参数类型模板参数和非类型模板参数如何相互约束? - How do variadic type template parameters and non-type template parameters of the template template parameter of a nested class constrain each other? 多态,可变参数模板继承,切片,boost :: any类型转换 - Polymorphism, variadic template inheritance, slicing, boost::any type cast 如何从可变种类的模板类包中的每种类型中恢复非类型名模板参数? - How can a recover the non-typename template argument from each type in a variadic pack of template classes? 每种可变参数模板的调用权模板专门化 - Call right template specialization for each type of a variadic template 如何将可变参数函数模板中的每个参数转换为另一种类型并获取其地址? - How can I convert each parameter in a variadic function template to another type and obtain its address?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM