为什么 "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};
也是如此,但被贬低了)。
[现代有效 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};
也是如此,但被贬低了)。