简体   繁体   English

如何模拟一个带有模板化args的函数,并在c ++中对它们应用模板化函数?

[英]How do I template a function that takes templated args and applies a templated function on them in c++?

I have a bunch of static class functions that take in varying number of {string, int, float} params and an Output param. 我有一堆静态类函数,它们接受不同数量的{string,int,float}参数和一个输出参数。 There may be different behavior for the same parameters based on the function called. 基于所调用的函数,相同参数可能存在不同的行为。 For example: 例如:

static void ChangeOutput1(const string& foo, int bar, Output* output);
static void ChangeOutput2(int bar, Output* output);
static void ChangeOutput3(float foo, Output* output);
static void ChangeOutput4(float foo, Output* output);  // behaves differently from ChangeOutput3

I'd like to have a simple, safe way of writing templates to perform a similar behavior over each of the functions, basically calling with an Output argument and converting it to a string to return. 我希望有一种简单,安全的方法来编写模板来对每个函数执行类似的行为,基本上使用Output参数调用并将其转换为要返回的字符串。 Ideally without having to specify the parameter types again. 理想情况下,无需再次指定参数类型。 It might look something like this: 它可能看起来像这样:

template<typename... Args, int (*ChangeOutputFn)(Args...)>
string OutputString(Args... args) {
    Output output;
    ChangeOutputFn(args..., &output);
    return ConvertToString(output);
}

// Is there a way to alias static templated functions?
using StringOutput1 = OutputString<ChangeOutput1>;
using StringOutput2 = OutputString<ChangeOutput2>;
using StringOutput3 = OutputString<ChangeOutput3>;

I'm not sure how to achieve this. 我不知道如何实现这一目标。 I'm both unsure of how to write OutputString and how I would alias or define the static functions. 我不确定如何编写OutputString以及如何别名或定义静态函数。 There are less elegant solutions, but they require repetitive boilerplate that I'd like to avoid. 有一些不太优雅的解决方案,但它们需要重复的样板,我想避免。

With a class, you may do something like: 通过课程,您可以执行以下操作:

template <typename T, T f> struct OutputString;

template<typename... Args, void (*ChangeOutputFn)(Args...)>
struct OutputString<void (*)(Args...), ChangeOutputFn>
{
    template <typename ... Ts>
    auto operator()(Ts... args)
    -> decltype(ChangeOutputFn(std::forward<Ts>(args)..., std::declval<Output *>()),
                std::string{})
    {
        Output output;
        ChangeOutputFn(std::forward<Ts>(args)..., &output);
        return ConvertToString(output);
    }
};

And then 然后

using StringOutput1 = OutputString<decltype(&ChangeOutput1), &ChangeOutput1>;
using StringOutput2 = OutputString<decltype(&ChangeOutput2), &ChangeOutput2>;
using StringOutput3 = OutputString<decltype(&ChangeOutput3), &ChangeOutput3>;

and use it as 并用它作为

std::string s2 = StringOutput2{}(42);
std::string s3 = StringOutput3{}(4.2f);

Demo 演示

You can do this if you move the Output argument to the front. 如果将Output参数移到前面,则可以执行此操作。

static void ChangeOutput1(Output*, const std::string& foo, int bar);
static void ChangeOutput2(Output*, int bar);
static void ChangeOutput3(Output*, float foo);
static void ChangeOutput4(Output*, float foo);

Now you can have this template: 现在你可以拥有这个模板:

template<typename... Args>
std::function<std::string(Args...)>
mkOutput (void (*ChangeOutputFn)(Output*, Args...))
{
    return [ChangeOutputFn](Args... args)->std::string{
        Output output;
        ChangeOutputFn(&output, args...);
        return ConvertToString(output);
    };
}

and "function aliases" look like this: 和“函数别名”看起来像这样:

auto a1 = mkOutput(ChangeOutput1);
auto a2 = mkOutput(ChangeOutput2);
auto a3 = mkOutput(ChangeOutput3);
auto a4 = mkOutput(ChangeOutput4);

Note 1. You cannot have this syntax 注意1.您不能使用此语法

OutputString<ChangeOutput1>

because ChangeOutput1 is a value and OutputString must either know its type beforehand or receive it as another template argument. 因为ChangeOutput1是一个值,而OutputString必须事先知道它的类型或者将它作为另一个模板参数接收。

It is possible to have something like this 有可能有类似的东西

OutputString<decltype(ChangeOutput1), ChangeOutput1>

and then eliminate the repetition with a macro, but that's just ugly. 然后用宏消除重复,但这只是丑陋。

I choose to pass the function at run time rather than at compile time, it's easier this way. 我选择在运行时而不是在编译时传递函数,这样更容易。

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

相关问题 如何在 c++/c++20 中创建 function 的模板化模板特化? - How do I create a templated template specialization of a function in c++/c++20? C++ 模板化 function 专业化模板 - C++ Templated function specialization with template C++ 模板化子类 arguments 到模板化 function - C++ templated subclass arguments to templated function C ++ - 如何在模板化类之外实现模板化成员函数 - C++ - how to implement templated member function outside a templated class 如何通过 C++ 中模板化类型的子类传递模板化 function 参数? - How to pass a templated function parameter with a subclass of the templated type in C++? 如何在C ++中将模板化的成员函数专门化为模板化的类? - How to specialize a templated member-function into a templated class in C++? 如何为模板化类型提供模板功能的专业化? - How do I provide specialization of template function for a templated type? 如何在C ++中的另一个模板函数中使用属于模板化类的嵌套类型? - How can I use a nested type belonging to a templated class in another template function in C++? 如何在 C++ 中为模板化函数创建宏 - How to create a macro for a templated function in c++ 如何将模板化的向量传递给C ++函数? - How to pass a templated vector to a C++ function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM