Aco*_*gua 12 c++ initializer initializer-list language-lawyer c++17
来自另一个问题:
由于C++ 17,auto x0{1, 2, 3, 4};以前推断出初始化列表,不再允许(当然,我们可以使用auto x0 = {1, 2, 3, 4};...).现在一如既往地避免统一初始化(例如std::vector<int> v({1, 2, 3, 4});,使用初始化列表作为参数进行显式构造函数调用),并且类似于定义良好auto x(7);(我不会自己使用的构造......),我想出了以下内容:
auto x({1, 2, 3, 4});
// -> std::initializer_list<int> x({1, 2, 3, 4});
Run Code Online (Sandbox Code Playgroud)
这是用GCC 7.2.0(mingw64)编译的,但是发出警告(而评论版再次没有):
list-initializer for non-class type must not be parenthesized
我在标准中找不到任何相关内容,所以现在的问题是(出于纯粹的兴趣......):
为什么不允许这样做?(这是否被标准所涵盖,或者我们是否需要将此视为GCC错误?)
这是不正确的.简而言之,braced-init-list不能在模板参数推导中推导出来,它被认为是非推导的上下文.
6)参数P,其A是braced-init-list,但P不是std :: initializer_list或对一个的引用:
首先,自动类型推导使用函数调用中的模板参数推导规则.[dcl.type.auto.deduct/4
(强调我的)
如果占位符是自动类型说明符,则使用模板参数推导的规则确定推断类型T'替换T. 通过用新发明的类型模板参数U替换auto的出现来获取P,或者如果初始化是copy-list-initialization,则用
std?::?initializer_list<U>.使用函数调用中模板参数推导的规则推导U的值,其中P是函数模板参数类型,相应的参数是e.如果扣除失败,则声明格式不正确.[例如:Run Code Online (Sandbox Code Playgroud)const auto &i = expr;i的类型是下面发明的函数模板的调用f(expr)中参数u的推导类型:
Run Code Online (Sandbox Code Playgroud)template <class U> void f(const U& u);- 结束例子]
注意auto x({1, 2, 3, 4});是直接初始化,而不是复制初始化,那么本发明的类型模板参数只是U,而不是std?::?initializer_list<U>,相应的参数是{1, 2, 3, 4}.
并且在函数调用的模板参数推导中,不能从braced-init-list推导出模板参数.[temp.deduct.call]/1
模板参数推导是通过将包含参与模板参数推导的模板参数的每个功能模板参数类型(称为P)与调用的相应参数的类型(称为A)进行比较来完成的,如下所述.如果从P中删除引用和cv限定符,则为某些P'和N提供std :: initializer_list或P'[N],并且该参数是非空的初始化列表([dcl.init.list]),然后扣除而是对初始化列表的每个元素执行,将P'作为函数模板参数类型并将初始化元素作为其参数,并且在P'[N]情况下,如果N是非类型模板参数,则N是从初始化列表的长度推导出来.否则,初始化列表参数会将参数视为非推导上下文([temp.deduct.type]).[例如:
Run Code Online (Sandbox Code Playgroud)template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T- 结束例子]
| 归档时间: |
|
| 查看次数: |
387 次 |
| 最近记录: |