Template function accepting callable functors with X parameters

こ雲淡風輕ζ 提交于 2019-12-11 07:35:50

问题


I'm writing a hosted C++ program that runs user-written C-code compiled on the fly. It's absolutely vital that certain typical exceptions are caught from the C-code and processed/ignored. To do this, I'm calling the C code from within a structured exception handling block. Due to the nature and semantics of this block (and where it's called from), I've separated the actual calling to it's own function:

    template <typename ret_type, class func>
        static ret_type Cstate::RunProtectedCode(func function) {
            ret_type ret = 0;
            __try {
                ret = function();
            }
            __except(ExceptionHandler(GetExceptionCode(), ExceptionStatus::CSubsystem)) {
                fprintf(stderr, "First chance exception in C-code.\n");
            }
            return ret;
        }

Which works nicely as it should like so:

        RunProtectedCode<int>(entry);

But is it possible to shape this so i can call functions with variable amounts of parameters - maybe through some use of exotic functors (only requirement is obviously that it can't have a destructor)? I'm using MSVC++ 2010.


回答1:


If you can use C++11 you can achive this with variadic tempaltes.

template <typename ret_type, class func, typename... Args>
    static ret_type Cstate::RunProtectedCode(func function, Args&&... args) {
        ret_type ret = 0;
        __try {
            ret = function(std::forward<Args>(args)...);
        }
        __except(ExceptionHandler(GetExceptionCode(), ExceptionStatus::CSubsystem)) {
            fprintf(stderr, "First chance exception in C-code.\n");
        }
        return ret;
    }

And you can call it like

RunProtectedCode<int>(entry2, 1, 2);
RunProtectedCode<int>(entry3, 1, "a", 3);

You can simplify it (kind of) by using std::function instead.

template <class func, typename... Args>
    static 
    typename func::result_type Cstate::RunProtectedCode(func function, Args&&... args) {
        typename func::result_type ret = typename func::result_type();
        __try {
            ret = function(std::forward<Args>(args)...);
        }
        __except(ExceptionHandler(GetExceptionCode(), ExceptionStatus::CSubsystem)) {
            fprintf(stderr, "First chance exception in C-code.\n");
        }
        return ret;
    }

And you can call it like

std::function<int(int,int,int)> entry_f = entry;
RunProtectedCode(entry_f,1,2,3);



回答2:


You can bind all arguments to your function making it effectively 0-ary functor, e.g. using std::bind (available in VC2010) or boost::bind (I prefer this one because VC implementation contains broken std::cref). Binding can be done in overloaded function before passing to RunProtectedCode, e.g. something like this:

template<typename R>
R(*f)() wrap(R(*f)())
{
    return f;
}

template<typename R, typename A>
boost::function<R(A)> wrap(R(*f)(), A a)
{
    return boost::bind(f, a);
}

template<typename R, typename A1, typename A2>
boost::function<R(A1, A2)> wrap(R(*f)(), A1 a1, A2 a2)
{
    return boost::bind(f, a1, a2);
}


来源:https://stackoverflow.com/questions/16589146/template-function-accepting-callable-functors-with-x-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!