【问题标题】:How do I return the called function's return statement in the template function?如何在模板函数中返回被调用函数的返回语句?
【发布时间】:2023-01-02 03:07:49
【问题描述】:

我想设计一个功能。此函数将采用 2 个参数。第一个参数将是包含函数名称的枚举类对象,第二个参数将是可变的。在我要设计的这个函数中,我希望使用来自可变参数的参数调用该函数,无论哪个函数名称来自枚举类对象。

这些被调用函数的签名彼此完全不同。无论被调用函数返回什么值,它都应该在我将要编写的函数中返回该值。这个return语句可以是类类型,也可以是double、long等基本类型。

结果,我希望能够按如下方式使用此功能。

enum class FunctionNames {
   func1,
   func2,
};

Myclass func1(int a, int b);
double func2();

int main() {
    auto res1 = call_function(FunctionNames::func1, 10, 20);
    auto res2 = call_function(FunctionNames::func2);
}

我试过 std::invoke。 std::invoke 将参数作为函数指针。实际上我可以使用 std::invoke。注意:我的编译器版本是C++17。

我想要一个像下面代码一样的功能。但是这样它会给出语法错误。

template <typename... Args>
auto myFunction(FunctionNames functionName, Args... args) {
    switch(functionName) {
        case FunctionNames::func1:
            return std::invoke(func1, std::forward<Args>(args)...);
        case FunctionNames::func2:
            return std::invoke(func2, std::forward<Args>(args)...);
        // Add more cases here for each function you want to call
    }

    return result;
}

【问题讨论】:

  • 请复制并粘贴该语法错误
  • 我没有费心去测试它,但也许if constexpr (functionName == FunctionNames::func1) return func1(std::forward&lt;Args&gt;(args)...); [else] if ...etc....
  • 你到底想通过这种方式达到什么目的?它对我来说似乎没有意义:如果您已经知道枚举值,那么您就知道要调用的函数,因此可以直接调用它。如果您不知道实际调用哪个函数,那么您如何知道要使用哪些参数?
  • 如果没有允许在编译时做出决定的常量表达式,这是不可能的,因此您不能根据传递的参数值返回不同的东西;您唯一的选择是返回类似std::variant&lt;...&gt; 的内容。此外,std::forward 只有在您实际使用转发引用时才有意义,而您在这里没有这样做。
  • 从根本上说,C++ 不是这样工作的。这是一个 XY 问题。你应该解释你试图解决的真正问题。不,这不是关于编写这种模板函数的问题,而是您认为解决方案是编写这种模板函数的问题。

标签: c++ templates c++17 variadic-templates typetraits


【解决方案1】:

如果您坚持使用这种方法,那么我认为您可以做到的唯一方法是让返回函数指针的函数强制转换为void *,然后像这样调用它:

template <typename P, typename... Args>
auto call_function(FunctionNames functionName, Args&&... args) {
    void *func = getFuncFromName(functionName);
    return std::invoke(reinterpret_cast<P *>(func), std::forward<Args>(args)...);
}

int main() {
    auto res1 = call_function<Myclass(int, int)>(FunctionNames::func1, 10, 20);
    auto res2 = call_function<double()>(FunctionNames::func2);
}

但我想重申,这是一种容易出错的方法,会给函数调用增加不必要的开销。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    • 2011-10-26
    • 2011-06-06
    相关资源
    最近更新 更多