为什么我不能使用带有 auto 的大括号初始化值并将其传递给此函数
Why can't I initialize a value using braces with auto and pass it into this function
为什么我不能用auto初始化一个值,并将其传递给一个需要decltype作为参数的函数
让我来设置场景,并向您展示一个小程序。
这是一个返回值的函数。
int Function(void);
在这种情况下,它恰好是一个整数,但返回类型可能会更改
这就是为什么下一个函数是这样写的:
void What_I_Take_Depends_On_Function(decltype(Function()) x);
如果有人决定更改函数的返回类型,则不需要更改此函数的减速。是的,函数的定义可能无法正确处理新类型,或者如果函数的返回类型更改为void,则会出现问题,但这与我的问题无关。
#include <iostream>
#include <cstdlib>
int Function(void){return 5;}
void What_I_Take_Depends_On_Function(decltype(Function()) x){return;}
int main(){
//assignments(Edit: these are initializations)
int var1 = Function();
auto var2 = Function();
//initializations
int var3 {Function()};
auto var4 {Function()};
What_I_Take_Depends_On_Function(var1); //works
What_I_Take_Depends_On_Function(var2); //works
What_I_Take_Depends_On_Function(var3); //works
What_I_Take_Depends_On_Function(var4); //COMPILER ERROR
//cannot convert ‘std::initializer_list<int>’ to ‘int’ for argument ‘1’ to ‘void What_I_Take_Depends_On_Function(int)’
return EXIT_SUCCESS;
}
那么,为什么var4是initializer_list而不是int呢
不能自动推断Function将返回int,
然后将减速度改为类似var3的减速度?
大括号初始化列表{...}
是C++11的新统一初始化语法,它可以用于初始化任何自动、静态或成员变量,如果该变量的类型已知。以下是有效的C++11初始化的几个例子:
class S
{
private:
int _m;
public:
S(int m) : _m { m } // <== initialization of a member
{}
};
int main() {
constexpr unsigned i { 10 }; // <== initialization of a constexpr
S s { i }; // <== initialization by calling constructor
/* ... */
}
在中,上述任何情况都不会生成std::initializer_list
。括号初始化列表{...}
只是意味着编译器将尝试为给定的数据类型识别一个合适的构造函数,其参数列表与括号初始化列表的内容匹配(§8.5.4)。
有两种特殊情况:
如果为给定数据类型定义的构造函数之一将
std::initializer_list<T>
作为参数,并且大括号init列表的内容都可以隐式转换为T
。当你使用一种内置的容器类型时,就会出现这种情况,例如std::vector<int> vec { 1, 2, 3 };
std::vector<T>
有一个构造函数std::vector<T>(const std::initializer_list<T>)
,因此大括号init列表将被转换为std::initializer_list<int>
,并因此被复制到向量构造函数中。构造函数将遍历列表,并逐个追加元素。当列表只包含一个参数时,这有点像陷阱:
std::vector<int> vec { 10 };
在这里,同样的情况也会发生,所以您将得到一个包含一个元素
10
的向量。这与使用旧式语法不同:std::vector<int> vec(10);
这将调用
std::vector<int>(const size_t)
构造函数,即创建一个包含10个默认初始化元素的向量。如果要初始化的变量的类型不是预先确定的,即当声明中使用
auto
时:auto v { 1, 2, 3 };
在这种情况下(§7.1.6.4/6),编译器无法确定合适的构造函数,因为任何采用三个整数(或可转换为整数)参数的数据类型都是可能的候选者。这里的规则是编译器假定
std::initializer_list<int>
为v
的数据类型。这也是你的情况。
换句话说,对于初始化来说,使用大括号init列表是可以的(甚至是鼓励的),但您不能很容易地将其与auto
结合起来。为了解决您的问题,您需要显式地声明数据类型
int var4 { Function() };
或者,为了保持灵活性,也可以在此处使用decltype
:
decltype(Function()) var4 { Function() };
或者,您可以使用旧式语法:
auto v (Function());
否,auto
不会"只是推断Function将返回int";auto说明符的工作方式在7.1.6.4中进行了定义,如下所示:
(7.1.6.4/p6)一旦根据8.3确定了声明符id的类型,则声明变量的类型使用声明符id是使用模板参数的规则根据其初始值设定项的类型确定的演绎设
T
是已经为变量标识符d
确定的类型。通过以下方式从T
获得P
用新发明的类型模板参数U
替换auto
的出现,或者,如果初始值设定项是braced-init-list
(8.5.4),具有std::initializer_list<U>
。则为变量d
推导的类型为使用来自函数调用的模板参数推导规则确定的推导出的CCD_ 26(14.8.1.1),其中CCD_ 27是函数模板参数类型,CCD_。如果扣除失败,申报不正确。
我对语法有误解
我习惯于初始化这样的变量:
int i{0};
但是,我需要用括号而不是括号来初始化这个类型
谢谢Raymond
- 正在初始化函数指针的constexpr数组
- 我应该在C++中使用构造函数还是初始化函数
- 使用 extern const 初始化函数
- 初始化函数中的静态变量,而不是在文件开始时
- 如何初始化函数中指针数组的大小
- 正在初始化初始化函数中的静态类成员
- call_once初始化函数
- SWIG + CMAKE:缺少初始化函数
- 如何创建在 c++ 中只读取一次的初始化函数
- 类内的强制初始化函数
- 使用元编程在编译时初始化函数数组
- 数组初始化函数:将数组作为指针传递:C++
- 从nodejs模块初始化函数报告失败
- 导入错误:动态模块未定义初始化函数
- 大括号初始化函数指针数组:从 'void (*(*)())()' 到 'void (*)()' 的转换无效
- 奇怪的行为,用 int 初始化函数指针
- 使用 init_seg 调用初始化函数
- 正在初始化函数内部的std::数组
- 初始化函数内部的指针.它是如何工作的
- JNI初始化函数以及缓存类和字段