【问题标题】:Template neglects const (why?)模板忽略了 const(为什么?)
【发布时间】:2012-10-27 17:35:50
【问题描述】:

有人知道,为什么会这样编译吗??

template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
class FrontBackBuffer{

public:


  FrontBackBuffer(
    const TBufferTypeFront  front, 
    const TBufferTypeBack back):    ////const reference  assigned to reference???
     m_Front(front),
     m_Back(back)
  {
  };

  ~FrontBackBuffer()
  {};

  TBufferTypeFront m_Front;       ///< The front buffer
  TBufferTypeBack m_Back;         ///< The back buffer

};

int main(){
    int b;
    int a;
    FrontBackBuffer<int&,int&> buffer(a,b); //
    buffer.m_Back = 33;
    buffer.m_Front = 55;
}

我使用 GCC 4.4 编译。为什么它甚至让我编译这个?不应该出现我无法将 const 引用分配给非常量引用的错误吗?

【问题讨论】:

  • 函数签名中忽略顶级 const-volatile 限定符。
  • AFAIK 常量引用不存在。您只能引用 const 对象(const int&amp; 有效,int&amp; const 不存在)。但是,这并不能解决您的问题...
  • 构造函数的参数名称为什么要以m为前缀?不是代表会员吗?它的目的不就是区分成员对象与函数局部对象和全局对象吗?
  • m_ 代表成员是,是的,它是一个错误:-)

标签: c++ templates constructor constants default-constructor


【解决方案1】:

问题是如果T 类型是int&amp;,那么const T 类型就不是const int&amp;,而是int &amp; const。在模板替换和 typedef 结果中忽略引用上的非法顶级 const。

另一方面,如果T 是const int,那么T&amp; 是const int&amp;

【讨论】:

  • @Gabriel,如果你知道如何发音类型,那就不是那么多了。 const int & 发音为“对 const int 的引用”,而非法的 int & const 将是“对(非 const)int 的 const 引用”。因此,如果 T 是“对 int 的引用”,那么 const T 是“对 int 的 const 引用”。如果 T 是 const int,则 T& 是对 const int 的引用。希望这很清楚
  • 谢谢,所以奇怪的是 T = reference to int = int& 产生然后 "const T" = const int & -> 其中 const 被忽略并且有 int & .... 就是这样不直观不是吗?理解来自像“const int & a = 2”这样的普通代码,这基本上是错误的形式(从右到左:引用 int const = 引用 const int)...
【解决方案2】:

当 TypeBufferFront 为 int&amp; 时,const TBufferTypeFront 等效于 int&amp; const,其中 const 在模板替换期间被忽略,因为所有引用都是常量,即使它们引用的不是。

因此,当使用int&amp; 实例化时,您的构造函数实际上是FrontBackBuffer(int&amp;, int&amp;),它按给定的方式工作。

这是为什么许多人会使用T const 而不是const T 的一个示例,以便更清楚地了解替换是如何发生的,并允许他们从右到左阅读 cv 限定符。

【讨论】:

  • 所以我可以将其理解为:const int & const -> 并且 const 被忽略了吗?
  • @Gabriel:不,关键是如果合法,const int&amp; const 与int const&amp; const 相同,是对常量整数的常量引用。在模板替换期间,int const&amp; const(不合法)被缩减为 int const&amp;(合法)。
【解决方案3】:

要让代码做你想做的事,它必须是这样的:

  FrontBackBuffer(
    typename std::remove_reference<TBufferTypeFront>::type const&  m_front, 
    typename std::remove_reference<TBufferTypeBack>::type const& m_back):    ////const reference  assigned to reference???
    m_Front(m_front),
    m_Back(m_back)
  {
  };

它有一个额外的“特性”,当用于构造FrontBackBuffer时,它会将其他类型转换为常量引用。

现在这并不完美。这可以防止FrontBackBuffer 的临时参数被移动,并且通过引用而不是通过值传递甚至很小的廉价复制类型(如char)。有标准的 C++0x 技术可以做到这一点,如果你在乎的话,写起来有点尴尬。

【讨论】:

【解决方案4】:

FrontBackBuffer::m_Front 是 TBufferTypeFront 类型,在您的模板实例化中转换为 int&amp;。分配给int&amp; 没有任何问题。

【讨论】:

  • 将int&amp; 绑定到const int&amp; 有问题。 Gabriel 认为构造函数的参数是const int&amp; 类型的,这就是问题所在。
猜你喜欢
  • 2022-12-23
  • 1970-01-01
  • 2016-06-12
  • 2013-09-30
  • 2016-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
相关资源
最近更新 更多