【问题标题】:Check function pointer for nullptr in a template for any kind of callable检查模板中 nullptr 的函数指针以获取任何类型的可调用
【发布时间】:2020-01-10 18:23:16
【问题描述】:

我创建了简单的wrapper 来捕获、报告和重新抛出异常(见下文)。它适用于函数、函数指针和 std::function 对象,但由于检查 nullptr 而无法编译 lambda 和仿函数。有没有办法尽可能简单地解决这个问题,以便包装器可以用于任何类型的可调用对象?谢谢!

#include <functional>

template<typename Func, typename TRet, typename... Args>
TRet wrapper(Func func, TRet exit_code_on_error, Args... args) {
    TRet exit_code = exit_code_on_error;
    //if (func) // this condition does not compile for lambdas and functors
    {
        try {
            exit_code = func(std::forward<Args>(args)...);
        } catch(...) {
            // report and possibly rethrow
            //throw;
        }
    }
    return exit_code;
}

int test1(double d) {
    return (int)d;
}

int test2(std::function<int (double)> f, double d) {
    return f(d);
}

struct TestFunctor {
    int operator()(double d) {
        return (int)d;
    }
};

int main() {
    // OK:
    wrapper(test1, 1, 2.3);
    wrapper(&test1, 1, 2.3);
    auto p = test1;
    wrapper(p, 1, 2.3);
    p = nullptr;
    wrapper(p, 1, 2.3);
    wrapper(test2, 1, test1, 2.3);

    // These lines cause the troubles:
    wrapper([](double d){ return (int)d; }, 1, 2.3);
    wrapper(TestFunctor(), 1, 2.3);
}

错误:

wrapper.hpp: error C2451: conditional expression of type 'Func' is illegal
        with
        [
            Func=main::<lambda_1>
        ]

【问题讨论】:

    标签: c++ templates lambda


    【解决方案1】:

    我们可以通过首先检查Func 是否为指针类型来解决此问题,如果是,则检查它是否为空指针。看起来像

    template<typename Func, typename TRet, typename... Args>
    TRet wrapper(Func func, TRet exit_code_on_error, Args... args) {
        if constexpr(std::is_pointer_v<Func> ||
                     std::is_member_function_pointer_v<Func> ||
                     std::is_same_v<Func, std::function<TRet(Args...)>>) {
            // this will only be compiled if Func is a pointer type or std::function
            if (func == nullptr)
                return exit_code_on_error;
        }
        try {
            return func(std::forward<Args>(args)...);
        } catch(...) {
            // report and rethrow if needed
            //throw;
        }
        return exit_code_on_error;
    }
    

    【讨论】:

    • 太棒了,就像一个魅力,就像我梦寐以求的那样简单:) 谢谢!
    • 小姐std::function.
    • added 检查 std::function 的答案:std::is_same_v&lt;Func, std::function&lt;TRet(Args...)&gt;&gt;
    猜你喜欢
    • 2021-10-28
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    相关资源
    最近更新 更多