c – 如何存储通用引用

前端之家收集整理的这篇文章主要介绍了c – 如何存储通用引用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要在类中存储通用引用(我确信引用的值将比类更长).这样做有规范的方法吗?

这是我提出的最小例子.它似乎有效,但我不确定我是否做对了.

template <typename F,typename X>
struct binder
{
    template <typename G,typename Y>
    binder(G&& g,Y&& y) : f(std::forward<G>(g)),x(std::forward<Y>(y)) {}

    void operator()() { f(std::forward<X>(x)); }

    F&& f;
    X&& x;
};

template <typename F,typename X>
binder<F&&,X&&> bind(F&& f,X&& x)
{
    return binder<F&&,X&&>(std::forward<F>(f),std::forward<X>(x));
}

void test()
{
    int i = 1;
    const int j = 2;
    auto f = [](int){};

    bind(f,i)();   // X&& is int&
    bind(f,j)();   // X&& is const int&
    bind(f,3)();   // X&& is int&&
}

我的推理是正确的还是会导致微妙的错误?另外,是否有更好(即更简洁)的方式来编写构造函数?粘合剂(F& f,X& x)将不起作用,因为它们是r值参考,因此不允许粘合剂(f,i).

解决方法

你不能“存储通用引用”,因为没有这样的东西,只有rvalue引用和左值引用. “通用参考”是Scott Meyers描述语法特征的方便术语,但它不是类型系统的一部分.

要查看代码的具体细节:

template <typename F,X&& x)

在这里,您使用引用类型实例化绑定器作为模板参数,因此在类定义中不需要将成员声明为rvalue-references,因为它们已经是引用类型(由bind推导的左值或右值).这意味着你总是得到更多&&比需要的标记,由于参考折叠而冗余并消失.

如果您确定绑定器将始终实例化绑定器(因此始终使用引用类型进行实例化),那么您可以像这样定义它:

template <typename F,typename X>
struct binder
{
    binder(F g,X y) : f(std::forward<F>(g)),x(std::forward<X>(y)) {}

    void operator()() { f(std::forward<X>(x)); }

    F f;
    X x;
};

在这个版本中,类型F和X是参考类型,因此使用F&&amp ;;和X&&因为它们或者已经是左值引用(所以&&什么也没做)或者它们是右值引用(所以&&&也没有做任何事情!)

或者,您可以保留绑定器,并将绑定更改为:

template <typename F,typename X>
binder<F,X> bind(F&& f,X&& x)
{
    return binder<F,X>(std::forward<F>(f),std::forward<X>(x));
}

现在,您使用左值引用类型或对象(即非引用)类型实例化活页夹,然后在内部活页夹中使用附加的&&来声明成员.所以它们是左值引用类型或右值引用类型.

此外,如果您考虑一下,则无需存储右值引用成员.通过左值引用存储对象是完美的,所有重要的是你在operator()函数中正确地将它们作为左值或右值转发.因此,班级成员可能只是F&和X& (或者在你总是使用引用参数实例化类型的情况下,F和X)

所以我会将代码简化为:

template <typename F,typename X>
struct binder
{
    binder(F& g,X& y) : f(g),x(y) { }

    void operator()() { f(std::forward<X>(x)); }

    F& f;
    X& x;
};

template <typename F,X>(f,x);
}

此版本在模板参数F和X中保留所需类型,并在std :: forward< X>(x)表达式中使用正确的类型,这是唯一需要它的地方.

最后,我发现在推导类型方面进行思考更准确,更有帮助,而不仅仅是(折叠)引用类型:

bind(f,i)();   // X is int&,X&& is int&
bind(f,j)();   // X is const int&,X&& is const int&
bind(f,3)();   // X is int,X&& is int&&

猜你在找的C&C++相关文章