繁体   English   中英

变量模板作为std :: function的参数

[英]Variadic template as parameters to std::function

我想构建一个允许我用未定义数量的参数调用成员函数的结构。 现在我写了这样的东西

template<typename Class, typename Return, typename ... Args>
struct Caller
{
private:
    std::function<Return(Args ...)> callerFunction;

    Caller() = delete;
    Caller(const Caller&) = delete;
    Caller(Caller&&) = delete;
    Caller& operator=(const Caller&) = delete;

public:
    ~Caller() = default;

    Caller(Class& instance, Return(Class::*function)(Args ...))
    {
        callerFunction = [&instance, function](Args... args)
        {
            return (instance.*function)(args ...);
        };
    }

    Return operator() (Args ... args)
    {
        return callerFunction(args ...);
    }
};

我担心我std::function<Return<Args&& ...)> callerFunction一个事实:我无法将std :: function变量声明为std::function<Return<Args&& ...)> callerFunction

当我尝试这样做时,编译器说它不能从int转换为int&& (例如,如果参数是int ),所以我猜测该函数将Args&& ...视为rvalue引用的参数包。 我对么?

有解决方法吗?

编辑:好的,我以错误的方式在Caller构造函数中声明了该函数。

错误的方式 - > Caller(Class& instance, Return(Class::*function)(Args&& ...))

正确的方法 - > Caller(Class& instance, Return(Class::*function)(Args ...))

(我猜)正确的实现是

template<typename Class, typename Return, typename ... Args>
struct Caller
{
private:
    std::function<Return(Args&& ...)> callerFunction;

    Caller() = delete;
    Caller(const Caller&) = delete;
    Caller(Caller&&) = delete;
    Caller& operator=(const Caller&) = delete;

public:
    ~Caller() = default;

    Caller(Class& instance, Return(Class::*function)(Args ...))
    {
        callerFunction = [&instance, function] (Args&&... args)
        {
            return (instance.*function)(std::forward<Args>(args) ...);
        };
    }

    Return operator() (Args&& ... args)
    {
        return callerFunction(std::forward<Args>(args) ...);
    }
};

现在的问题是:为什么我需要在没有double&?的情况下声明函数?

当您像这样定义类模板时:

template <typename T>
struct A {
 A(T&& param)
}

然后创建一个实例:

A<int> myInstance(someIntVariable);

它不会编译 原因是, T的类型由您明确指定(作为int ,在A<int> ),并且您的类构造函数参数不再是T&& ,而是int&& ,因此它不再是通用引用(它同时接受左值和右值参考),但是常规右值参考。

接下来,如果传递一些整数,则会出现类型不匹配错误,因为在期望rvalue引用时传递常规变量。

在您的示例中,您明确定义了函数签名,因此同样适用 - 构造函数需要一个函数将rvalue引用到Args ...,但事实并非如此。

我认为在这个问题中解释得更好

int&&int 如果您的方法采用int ,则不需要int&& 它们是不同的类型。

成员函数指针的不同签名之间没有转换。

转发引用并不神奇。 它们依赖于演绎规则(并且不使用上面的Args&&...在推导的上下文中)和参考折叠规则。

就这样,你的

Return operator() (Args&& ... args)

也是错的。 如果Args...int ,那么你将无法使用int a; blah.operator()(a)调用上面int a; blah.operator()(a) int a; blah.operator()(a)作为a不会绑定到int&&

老实说,你的整个类型应该被抛出并替换为std::function<Return(Args...)> Class是函数所做的无用的缩小,你的包装器也不会增加太多。

用户只需[&a](auto&&...args)->decltype(auto){ return a.foo(decltype(args)(args)...); } [&a](auto&&...args)->decltype(auto){ return a.foo(decltype(args)(args)...); }如果他们真的需要复制你的构造函数,或使用std::bind( &A::foo, std::ref(a) )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM