为什么 "auto" 在推导 return 值时不能接受 braced-init-list?

Why "auto" cannot accept braced-init-list when deducing return value?

[现代有效 C++] 说:

template<class T>
void f(T t){}
int main(){
    f({1,2,3});
}

会编译失败,因为模板实例化时,必须知道T的类型,而这里的{1,2,3}是braced-init-list。应该像这样修复:

auto x={1,2,3};//auto deduces x to std::initializer_list
f(x);

我能理解这个,但是我的问题是:

为什么书上继续说,用"auto"进行return值推导时,不能接受和推导braced-init-list?

auto f()
{
    return {1,2,3};
}

编译失败。

Emmmmm,如果这是 C++14 标准的一部分,我不明白为什么会有这样的限制?它继续说:

auto resetV=[&v](const auto& newValue){v=new Value;}

"newValue"前的"auto"也不能接受{1,2,3}。为什么我们有这两个限制?

我猜可能从语言设计的角度来看,在进行类型推导时会出现一些混乱?只是一个猜测。 这些设计决策有什么线索吗?这让我困惑了好几天。

谢谢。

Why the book continues to say, when using "auto" for return value deduction, it cannot accept and deduce braced-init-list?

不是"can't deduce it"。这是不允许的。仔细想想这段代码:

#include <initializer_list>

auto f() -> std::initializer_list<int>
{
    return {1,2,3};
}

它能编译吗?是的。安全吗?不会。这可能会在底层数组的生命周期中引入各种问题。 std::initializer_list 不应该像容器一样使用。

std::initializer_list 是对匿名数组的引用。

数组本身位于创建 initializer_list 的块范围内。

std::initializer_list<int> f() {
  return {1,2,3};
}

几乎完全没用,因为数组的生命周期是f的主体,而引用它的initializer_list存在于一段几乎完全不相交的代码中。

使用 initializer_list 几乎可以肯定是未定义的行为。你可能会问它的大小和它是否为空,这可能是定义的行为(不知道,不太关心检查),但你绝对不能检查它的内容。

初始化程序列表是对数据的引用,而不是数据的副本。

如果:

auto f() {
  return {1,2,3};
}

推导自己就是上面的,几乎没用。

唯一的例外是 auto x = {1,2,3}; 可以从一组 {} 中推导出 initailizer_list<int>。 (在 C++11 中,auto x{1}; 也是如此,但被贬低了)。