0

だから私はc ++ 11 Varidiacsをいじっていました.CallClassと呼ばれるものを作成したかったのですが、基本的には、すべての変数が設定されているときに、後で呼び出すために関数をワープするクラスです(本当に役立つかどうかはわかりません):

#include <tuple>

template <typename OBJ,typename F,typename... VARGS>
class CallClass
{
    public:

        CallClass(OBJ& object,F callFunction)
        :_object(&object),_func(callFunction)
        { }

        CallClass(const CallClass& other)
        :_func_args(other._func_args)
        ,_object(other._object)
        ,_func(other._func)
        { }

        template <size_t INDEX>
        auto get(){ return std::get<INDEX>(_func_args); }

        template <size_t INDEX,typename T>
        void set(const T& val){ std::get<INDEX>(_func_args) = val; }

        template <size_t INDEX,typename T>
        void set(T&& val){ std::get<INDEX>(_func_args) = val; }

        auto Call()
        {
            //throws segmentation Fault Here
            return InnerCall<0>(_func_args);
        }

        virtual ~CallClass() {}

    protected:

    private:
        std::tuple<VARGS...> _func_args;
        OBJ* _object;
        F _func;

        template <size_t INDEX,typename... ARGS>
        auto InnerCall(std::tuple<VARGS...>& tup,ARGS... args)
        {
            auto arg = std::get<INDEX>(tup);

            return InnerCall<INDEX + 1>(tup,args...,arg);
        }

        template <size_t INDEX,VARGS...>
        auto InnerCall(std::tuple<VARGS...>& tup,VARGS... args)
        {
            return (_object->*_func)(args...);
        }
};

コンパイルしようとすると (IDE:code::blocks を使用してコンパイルし、Windows で MINGW を使用するように構成)、 Compiler:Segmentation Fault, everyone any Ideas? が出力されます。

使用法:

class obj{
public:
    obj(int a)
    :_a(a)
    { }

    virtual ~obj() {}

    int add(int b,int c){
        return _a + b + c;
    }

private:
    int _a;
};

int main(){
obj ob(6);
CallClass<obj,decltype(obj::add),int,int> callAdd(ob,obj::add);

    callAdd.set<0,int>(5);
    callAdd.set<1,int>(7);
    cout << "result is " << callAdd.Call() << endl;

    return 0;
}
4

1 に答える 1

0

少し検索した後、ある意味で同様の問題に遭遇しました。どうやらタプルをアンパックする方法が問題なので、次のように別のアプローチを使用することにしました:ここにリンクの説明を入力してください

私のニーズに合わせていくつかの変更を追加する必要がありました:

変更:

namespace detail
{
    template <typename OBJ,typename F, typename Tuple, bool Done, int Total, int... N>
    struct call_impl
    {
        static auto call(OBJ& obj,F f, Tuple && t)
        {
            return call_impl<OBJ,F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(obj,f, std::forward<Tuple>(t));
        }
    };

    template <typename OBJ,typename F, typename Tuple, int Total, int... N>
    struct call_impl<OBJ,F, Tuple, true, Total, N...>
    {
        static auto call(OBJ& obj,F f, Tuple && t)
        {
            return (obj.*f)(std::get<N>(std::forward<Tuple>(t))...);
        }
    };
}

// user invokes this
template <typename OBJ,typename F, typename Tuple>
auto call(OBJ& obj,F f, Tuple && t)
{
    typedef typename std::decay<Tuple>::type ttype;
    return detail::call_impl<OBJ,F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(obj,f, std::forward<Tuple>(t));
}

Call() を変更しました:

auto Call()
{
    std::tuple<VARGS...> func_args = _func_args;
    return call(*_object,_func, std::move(func_args));
}

タプルを参照として渡したり、構造体をクラスの一部にするなど、さらにいくつかの変更を加える予定です。

于 2016-10-27T10:55:19.643 に答える