参考数据类型的变量模板

时间:2018-01-18 13:39:12

标签: c++ c++11 pass-by-reference variadic-templates stdtuple

我想为类方法创建一个包装器,所以我使用了一个变量模板和std :: tuple来包装方法。它按我的需要工作,但我无法弄清楚如何能够使用引用调用的参数包装方法。请参阅下面的主要功能。

#include <iostream>
#include <string>
#include <functional>

using namespace std::placeholders;

namespace helper {

template <std::size_t... Ts> struct index {};

template <std::size_t N, std::size_t... Ts> struct gen_seq : gen_seq<N - 1, N - 1, Ts...> {};

template <std::size_t... Ts> struct gen_seq<0, Ts...> : index<Ts...> {};

template<class F, class... Ts, std::size_t... Is> void for_each_in_tuple(std::tuple<Ts...> &tuple, F func, std::index_sequence<Is...>)
{
    using expander = int[];
    (void)expander {
        0, ((void)func(std::get<Is>(tuple)), 0)...
    };
}

template<class F, class...Ts> void for_each_in_tuple(std::tuple<Ts...> &tuple, F func)
{
    for_each_in_tuple(tuple, func, std::make_index_sequence<sizeof...(Ts)>());
}
}

enum class Result : std::int32_t {
    Result1 = 1,
    Result2 = 2
};

template<typename... Args> class Procedure {
private:

    std::function<Result(Args...)> m_method;
    std::tuple<Args...> args;

    template <typename... Args, std::size_t... Is> Result callMethod(std::tuple<Args...> &tup, helper::index<Is...>)
    {
        return  m_method(std::get<Is>(tup)...);
    }

    template <typename... Args> Result callMethod(std::tuple<Args...> &tup)
    {
        return callMethod(tup, helper::gen_seq<sizeof...(Args)> {});
    }

public:

    template <typename ...Args> void setMethod(const std::function<Result(Args &&... args)> &method)
    {
        m_method = method;
    }
};

class MethodsClass {

public:

    Result doSomething(std::int32_t input, double output)
    {
        return Result::Result1;
    }
};

int main()
{
    **// This works fine**
    MethodsClass methods;
    Procedure <std::int32_t, double> procedure1;
    procedure1.setMethod<std::int32_t, double>(std::bind(&MethodsClass::doSomething1, methods, _1, _2));

    **// This end with compiler error std::tuple<int32_t,double &>::tuple': no appropriate default constructor available**

    Procedure <std::int32_t, double &> procedure2;
    procedure2.setMethod<std::int32_t, double &>(std::bind(&MethodsClass::doSomething2, methods, _1, _2));

    return 0;
}

我知道为什么第二种情况不能编译,消息很清楚,显然必须初始化引用。但是在这种情况下如何做呢?如何初始化std:tuple,如何以及在何处扩展参数包?我错过了什么,无法实现。

1 个答案:

答案 0 :(得分:0)

好吧,在C ++ 17中,这很容易。必须声明元组:

IOException: socket CONNECT read failed socket might closed or timeout

然后可以简单地删除所有递归元组解包并替换为:

std::tuple<typename std::decay<Args>::type...> m_args;