返回统一的初始化参考是否有效?

此代码示例是否有效?

using ref = char&;

ref foo(ref x) {
  return ref{x};
}

int main() {
  char a;
  foo(a);
  return 0;
}

看起来:

  • 铿锵3.5说YES
  • gcc 4.9说不

    main.cpp: In function 'char& foo(ref)':
    main.cpp:4:15: error: invalid cast of an rvalue expression of type 'char' to type 'ref {aka char&}'
       return ref{x};
                   ^
    
  • http://coliru.stacked-crooked.com/a/cb6604b81083393f

    那么哪个编译器是对的? 还是没有指定?

    它很容易通过以下方式克服gcc构建错误:

  • 使用括号代替大括号

    ref foo(ref x) {
      return ref(x);
    }
    
  • 通过命名返回的值

    ref foo(ref x) {
      ref ret{x};
      return ret;
    }
    
  • 选项1.打破统一初始化,选项2.添加无用的代码行。

    类似的问题已经在这里提出:为什么我不能在初始化器列表中使用统一初始化来初始化引用?

    但是提到的pr50025在gcc 4.9中是固定的。

    我知道上面的代码示例是非常没用的,但我过于简单地指出了这个问题。 在现实生活中,代码问题可以隐藏在通用函数中,如:

    #include <utility>
    template <typename Tp, typename... Us>
    Tp bar(Us&&... us) {
      return Tp{std::forward<Us>(us)...};
    }
    

    这似乎是标准中的一个遗漏,GCC正在执行标准所要求的内容,而铿锵正在实现可能的目标。

    从C ++ 11(强调我的):

    5.2.3显式类型转换(功能符号)[expr.type.conv]

    1一个简单类型说明符(7.1.6.2)或类型名称说明符(14.6),后面跟着一个带括号的表达式列表,根据表达式列表构造一个指定类型的值。 如果表达式列表是单个表达式,那么类型转换表达式与相应的表达式(5.4)是等价的(在定义中,如果定义的话)。 [...]

    [...]

    3同样地,一个简单型或说明符类型名称说明符后跟一个支撑-INIT-列表中创建具有指定掺进-INIT-列表中指定的类型的直接清单初始化(8.5.4)的临时对象, 并且其值就是那个临时对象作为prvalue

    对于braced-init-list的情况,标准并没有指定它的作用就像C风格的转换。 它并没有:

    typedef char *cp;
    int main() {
      int i;
      (cp(&i)); // okay: C-style casts can be used as reinterpret_cast
      (cp{&i}); // error: no implicit conversion from int * to char *
    }
    

    不幸的是, T(expr)等价于(T)expr也是一个例外,其中一个功能强制转换不一定产生一个prvalue。 该标准未能为使用braced-init-list到引用类型的功能强制类型指定类似的异常。 因此,在你的例子中, ref{x}构造了一个从{x}初始化的类型ref ,direct-list的临时类型。 这个临时值被视为一个prvalue,因为这就是标准所说的行为应该是什么,并且这个prvalue不能用于绑定到一个左值引用。

    我强烈怀疑,如果这是由ISO C ++委员会提出的,那么标准将会改变为要求clang的行为,但是根据目前的标准措辞,我认为GCC是正确的,至少对于您的具体示例而言。

    您可以省略refTp )来避免该问题,而不是添加变量或切换到括号。

    template <typename Tp, typename... Us>
    Tp bar(Us&&... us) {
      return {std::forward<Us>(us)...};
    }
    
    链接地址: http://www.djcxy.com/p/24479.html

    上一篇: Is returning uniform initialized reference valid?

    下一篇: Is it a good pattern to raise exceptions in a python decorator?