首页 > 解决方案 > 如何使用可变参数模板编写通用函数包装器

问题描述

我刚刚开始沉迷于模板的高级使用。我正在尝试为函数编写一个通用包装器,以包装可能导致异常的函数。如果没有发生异常,包装函数应该将实际返回值写入某个引用,然后返回true。如果发生异常,它只返回false

代码

#include <string>
#include <iostream>
#include <functional>
#include <exception>
#include <iomanip>

template<typename TReturn, typename ... TArgs>
bool Try(std::function<TReturn(TArgs...)> &function, typename std::function<TReturn(TArgs...)>::result_type& res, TArgs&...args) {
    try {
        res = function(std::forward<TArgs>(args)...);

        return true;
    }
    catch (...) {
        return false;
    }
}

std::string foo(int val) {
    if (val == 0) {
        throw std::exception();
    }

    return "result";
}

int main() {
    std::string res = "noResult";

    //Should be "false=>noResult"
    std::cout << std::boolalpha << Try(foo, res, 0) << "=>" << res;

    //Should be "true=>result"
    std::cout << std::boolalpha << Try(foo, res, 1) << "=>" << res;
}

期望

我期望像这样的模板实例化bool Try(std::function<std::string(int)>& function, std::string& res, int&arg);

相反,它甚至没有编译:

错误:

没有函数模板“Try”的实例与参数列表匹配

'bool Try(std::function<_Ret(_Types...)>,std::function<_Ret(_Types...)>::result_type &,TArgs &...)': 无法推导出模板参数'std::function<_Ret(_Types...)>' 来自'std::string (int)'

我想我打电话的方式Try也可能有缺陷。


我发现了这个类似的问题,但我无法让它与返回类型一起使用。

是的,对于返回的函数,需要有一个特殊的重载void


我错过了什么,怎么能做到这一点?提前致谢!

标签: c++variadic-templates

解决方案


为什么这么多std::function

template<typename TReturn, typename ... TArgs>
bool Try(TReturn (&function)(TArgs...), TReturn& res, TArgs...args) {
    try {
        res = function(std::forward<TArgs>(args)...);

        return true;
    }
    catch (...) {
        return false;
    }
}

您也不能像0作为参考一样传递参数TArgs&...。照原样通过它们。


推荐阅读