【问题标题】:can auto type deduction possibly cause conversion error?自动类型扣除可能会导致转换错误吗?
【发布时间】:2011-06-18 22:46:22
【问题描述】:

我有一个非常简单的解析器规则(用于 AXE),如下所示:

auto space = axe::r_lit(' ');
auto spaces = space & space & space;

最后一行在 VC2010 中按预期编译和工作,但在 gcc 4.6 中给出了一个奇怪的错误:

parsers.cpp:68:34: error: conversion from 
'axe::r_and_t<
    axe::r_and_t<axe::r_char_t<char>&, axe::r_char_t<char>&>, 
    axe::r_char_t<char>&
>' to non-scalar type 
'axe::r_and_t<
    axe::r_and_t<axe::r_char_t<char>&, axe::r_char_t<char>&>&, 
    axe::r_char_t<char>&
>' requested

我想知道,这是否是 gcc 中的(已知)错误,以及是否有可能使用 auto 声明获得转换错误。 auto 的推导类型不应该总是与初始值设定项完全相同吗?

AXE overloads operator& 像这样:

template<class R1, class R2>
r_and_t<
    typename std::enable_if<
       is_rule<typename std::remove_reference<R1>::type>::value, R1>::type, 
    typename std::enable_if<
       is_rule<typename std::remove_reference<R2>::type>::value, R2>::type
>
operator& (R1&& r1, R2&& r2)
{
    return r_and_t<R1, R2>(std::forward<R1>(r1), std::forward<R2>(r2));
}

我无法将问题简化为一个简短的测试用例,不幸的是,每次我尝试提供简单示例时,它都会编译。

【问题讨论】:

  • 我们是否知道问题在于初始化 auto 变量,或者它是否是 &amp; 运算符之一的临时问题?
  • @Bo Persson:看起来问题出在auto,因为这行:space &amp; space &amp; space; 编译没有问题。查看错误消息,编译器正确识别了右侧类型,但由于某种原因决定为 auto 分配不同的类型,从而导致转换错误。
  • 这似乎与auto 无关,但事实上R1 在您的第二个&amp; 中使用(E &amp; space,其中E 是右值第一次使用&amp; 的结果似乎是T&amp;,而不是T(根据C++0x 的要求)。现在对我来说闻起来像是 GCC 问题。
  • @Johannes Schaub:是的,看起来编译器错过了右值,但即便如此,为什么它在 auto 的右侧和左侧会有不同的类型?
  • @Gene 问题不在于auto,我想。返回表达式的类型与operator&amp; 的第二个实例化的返回类型不匹配。但这表明R1operator&amp; 的主体中与声明部分中的类型不同。如果您将operator&amp; 更改为使用auto name() -&gt; ... 表示法,会有什么不同吗?只是猜测......

标签: c++ g++ c++11


【解决方案1】:

auto 并不总是完全是初始值设定项的类型,因为auto 正在删除引用,使其类型为T,而您期望T&amp;。如果您需要参考 - 拼写auto&amp;

【讨论】:

  • 那是正确的,我应该更准确地说它是 从初始化程序推导出来的,而不是使用 与初始化程序相同的类型,因为 same 受类型推导规则的约束,这些规则因不同的语言结构而异。但问题还是一样,编译器似乎在查找的两个阶段对类型的推断有所不同,我认为这是一个错误。
【解决方案2】:

不要评价这个答案,它仅供参考

这确实是以前版本的 gcc 的一个 bug,它在 gcc-4.7.0 中得到了修复。

【讨论】:

  • 这应该被投票并接受为正确答案,因为它可能会在未来帮助人们。
【解决方案3】:

问题出在参考文献中。

parsers.cpp:68:34: error: conversion from 
'axe::r_and_t<
    axe::r_and_t<axe::r_char_t<char>&, axe::r_char_t<char>&>, 
    axe::r_char_t<char>&
>' to non-scalar type 
'axe::r_and_t<
    axe::r_and_t<axe::r_char_t<char>&, axe::r_char_t<char>&>&, 
    axe::r_char_t<char>&
>' requested

第一个模板参数是axe::r_and_t&lt;axe::r_char_t&lt;char&gt;&amp;, axe::r_char_t&lt;char&gt;&amp;&gt;,第一个是axe::r_and_t&lt;axe::r_char_t&lt;char&gt;&amp;, axe::r_char_t&lt;char&gt;&amp;&gt;&amp;,第二个是axe::r_and_t&lt;axe::r_char_t&lt;char&gt;&amp;, axe::r_char_t&lt;char&gt;&amp;&gt;&amp;。这是模板参数不匹配 - 可能在返回值中。最有可能发生这种情况是因为 Visual Studio 的 SFINAE 实现充其量是狡猾的,它没有正确实现两阶段查找,而且 GCC 版本可能选择了与 Visual Studio 不同的重载。

【讨论】:

  • 重点是,如果使用auto,应该没有任何问题。除非问题确实出在space &amp; space &amp; space 上——但 OP 说这可以作为独立行编译。
  • 两条信息让我相信这是编译器错误。首先,很难想象auto 是如何导致这个错误的。其次,这个错误只出现在模板代码中。与 VC10 不同,Gcc 实现了两阶段查找,并且可能以某种方式在两个阶段推导了不同的类型。
【解决方案4】:

尝试使用这个版本的编译器:

axe::r_and_t<
axe::r_and_t<axe::r_char_t<char>&, axe::r_char_t<char>&>, 
axe::r_char_t<char>&
> spaces = space & space & space ;

会发生什么?

编辑添加:我刚刚注意到这个问题已经三个月了。所以没关系。但它有没有得到解决?

【讨论】:

  • 我倾向于认为这是编译器错误。我没有机会尝试更新版本的 gcc。如果使用实际类型而不是auto,则不会出错,如果在非模板函数中声明auto,也不会出错。我猜这是编译器两阶段查找错误,当第一次传递期间推断的类型与实例化期间推断的类型不同时。
猜你喜欢
  • 2014-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多