如何存储引用,当它是一个左值,存储一个副本,当它是一个右值 [英] How to store a reference when it is an lvalue, store a copy when it is an rvalue

查看:141
本文介绍了如何存储引用,当它是一个左值,存储一个副本,当它是一个右值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个可以用固定数量的参数调用的工厂函数模板,每个参数都有一个模板参数。有两个参数:

I want to make a factory function template that can be called with a fixed number of parameters, each parameter type a template parameter. With two parameters :

template< typename T1, typename T2 >
and_implementation< T1, T2 > and( T1 && p1, T2 && p2 ){
   return and_implementation< T1, T2 >( p1, p2 );
}

and_implementation 对象我想存储对一个左值的每个参数的引用,以及作为右值的每个参数的副本。我不想使用堆。

In the and_implementation object I want to store a reference to each parameter that is an lvalue, and a copy of each parameter that is an rvalue. I don't want to use the heap.

目标是当我写

auto p1 = ....
auto p2 = ....
auto p3 = and( p1, p3 );

p3 对象只包含 p1 p2 ,但是当我写如下时:

the p3 object contains only references to p1 and p2, but when I write something like

auto p1 = ....
auto p2 = ....
auto p3 = ....
auto p4 = and( p1, and( p2, p3 ));   

p4 对象包含引用 p1 ,但是和(p2,p3)的副本。

the p4 object contains a referencde to p1, but a copy of and(p2, p3).

有办法吗?

我想到的是(工厂被称为反转,只有一个参数)

What I came up with (the factory is called invert and has only one parameter) is

template< typename T >
struct invert_impl: public gpio {

   T pin;

   template< typename TT > invert_impl( TT && p ):  
      pin( p ) {} // this is line 60

};

template< typename P >
invert_impl< P > invert( P && pin ){
    return invert_impl< P >( pin );
}

这适用于

autp pin4 = lpc_gpio< 4 >{};
auto led = invert( pin4 );

autp pin4 = lpc_gpio< 4 >{};
auto led = invert( invert( pin4 ));

我得到(GCC 4.9.3):

I get (GCC 4.9.3):

main.cpp:60:14: error: invalid initialization of reference of type 'lpc_gpio<4>&' from expression of type 'invert_impl<lpc_gpio<4>&>'


推荐答案

你的构造函数不需要是一个模板,因为在每个具体的模板实例化,你已经知道你的构造函数应该接受的确切类型:它应该接受 T



You're over-thinking things. Your constructor doesn't need to be a template, since in every concrete template instantiation, you already know the exact type your constructor should accept: it should accept a T.

template <typename T>
struct invert_impl : public gpio {
  T pin;
  invert_impl(T p) : pin(p) {}
};

您的模板构造函数失败的原因是因为它也被选择为复制或移动构造函数(如果它是一个比隐式生成的复制和移动构造函数更好的匹配),这不能工作。复制和移动构造函数使用 const invert_impl& invert_impl&& ,不能用于初始化 pin

The reason your template constructor is failing is because it also gets selected as a copy- or move-constructor (if it's a better match than the implicitly generated copy- and move constructors), which cannot work. The copy- and move constructor take const invert_impl & and invert_impl &&, which cannot be used to initialise pin.

注意: pin p 可能在此处制作不必要的副本。 std :: forward 可以避免这种情况,即使这不是原来打算的。

Note: the initialisation of pin from p may be making an unnecessary copy here. std::forward can avoid that, even though this isn't exactly what it's originally intended for.

  invert_impl(T p) : pin(std::forward<T>(p)) {}






@Yakk正确地指出,即使这样仍然有一些不必要的操作,可以通过使构造函数代替,并从转换转发,如下所示:

template <typename T>
struct invert_impl : public gpio {
  T pin;
  invert_impl(T &&p) : pin(std::forward<T>(p)) {}
};

template <typename T>
invert_impl<T> invert(T &&pin) {
  return invert_impl<T>(std::forward<T>(pin));
}

这篇关于如何存储引用,当它是一个左值,存储一个副本,当它是一个右值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆