当返回语句时,逗号运算符,braced-init-list和std :: unique_ptr合并在一起
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当返回语句时,逗号运算符,braced-init-list和std :: unique_ptr合并在一起相关的知识,希望对你有一定的参考价值。
在下面的代码中,为什么在所有其他情况都还可以的情况下,为什么我得到n = 8
的编译错误?我的目的是报告一些错误并返回空指针,而不用不必要的花括号将代码弄乱。我将为此使用nullptr,但我很好奇{}
为什么无法使用逗号运算符进行编译而只能单独工作的原因。
您可以使用此代码here进行播放。我使用了C ++ 20设置。
#include <cstdint>
#include <memory>
void oops(const char*) {
}
std::unique_ptr<uint8_t[]> please_do(int n) {
if (n == 1)
return std::unique_ptr<uint8_t[]>(); // compiles ok
if (n == 2)
return oops(""), std::unique_ptr<uint8_t[]>(); // compiles ok
if (n == 3)
return std::make_unique<uint8_t[]>(n); // compiles ok
if (n == 4)
return oops(""), std::make_unique<uint8_t[]>(n); // compiles ok
if (n == 5)
return nullptr; // compiles ok
if (n == 6)
return oops(""), nullptr; // compiles ok
if (n == 7)
return {}; // compiles ok
if (n == 8)
return oops(""), {}; // why compilation error?
return nullptr; // compiles ok
}
int main() {
please_do(42);
return 0;
}
GCC 9.2输出:
<source>: In function 'std::unique_ptr<unsigned char []> please_do(int)':
<source>:26:26: error: expected primary-expression before '{' token
26 | return oops(""), {}; // why compilation error?
| ^
<source>:26:25: error: expected ';' before '{' token
26 | return oops(""), {}; // why compilation error?
| ^~
| ;
Clang 9.0.0输出:
<source>:26:16: error: no viable conversion from returned value of type 'void' to function return type 'std::unique_ptr<uint8_t []>'
return oops(""), {}; // why compilation error?
^~~~~~~~
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/unique_ptr.h:528:7: note: candidate constructor not viable: cannot convert argument of incomplete type 'void' to 'std::unique_ptr<unsigned char [], std::default_delete<unsigned char []> > &&' for 1st argument
unique_ptr(unique_ptr&& __u) noexcept
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/unique_ptr.h:533:12: note: candidate constructor template not viable: cannot convert argument of incomplete type 'void' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
constexpr unique_ptr(nullptr_t) noexcept
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/unique_ptr.h:681:7: note: candidate constructor not viable: cannot convert argument of incomplete type 'void' to 'const std::unique_ptr<unsigned char [], std::default_delete<unsigned char []> > &' for 1st argument
unique_ptr(const unique_ptr&) = delete;
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/unique_ptr.h:542:2: note: candidate template ignored: could not match 'unique_ptr<type-parameter-0-0, type-parameter-0-1>' against 'void'
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
^
<source>:26:24: error: expected expression
return oops(""), {}; // why compilation error?
^
[{}
没有类型,因此逗号运算符oops(""), {}
错误。
[return {};
对copy initialization进行特殊处理。
{}
不是表达式。 return {...};
是它自己的特殊语法(list initialization的一种形式),该语法从函数的签名中找出返回类型,就像Ret{...}
一样,其中Ret
是返回类型:
Ret f() {
return {...}; // special syntax for return; {args...} need not be a valid expression
}
// same as
Ret f() {
return Ret{...}; // generic return <expression> syntax; Ret{args...} must be a valid expression
}
return a, b
中没有特殊语法。只是使用常规a, b
语法返回的表达式return
。逗号运算符要求a
和b
都必须是表达式,但是由于{}
是not一个表达式,因此oops(""), {}
之类的表达式是无效的语法。
顺便说一句,在其他地方也可以使用{...}
,当实际上不是时,它看起来像是一个表达式。函数调用:
void f(std::string);
f({5, 'a'})
同样,虽然看起来{5, 'a'}
是类型为std::string
的表达式(按意图),但实际上不是。 {5, 'a'}
是函数调用本身的一部分,其类型由重载分辨率决定。
关于编译器错误,oops(""), {}
作为表达式的语法无效,这两个说法都令人困惑。 GCC似乎已读取oops(""),
,因此期望后面有一个表达式。但是表达式不能以{
开头,因此它读取该字符并立即倒钩,抱怨说它期望表达式开始。 lang做同样的事情。我认为Clang然后继续寻求“帮助”,假装您只是没有写, {};
部分(也就是说,就好像您写了return oops("");
)一样,并为此发出了错误,太。这种行为是例如是什么让Clang提供了有用的类型错误,即使您拼错了一些内容也是如此;也就是说,如果您要在[]上运行Clang,
void supercalifragilisticexpialidocious(std::string); int main() { supercalifragilisticexpialidociuos(7); }
首先会针对拼写错误(
-ous -> -uos
)发出错误,建议正确的拼写,然后针对int
7
和参数类型std::string
之间的类型不匹配发出错误。如果您已经解决了拼写错误。同样,在这里,它针对语法错误发出一个错误,然后发出第二种错误,就好像您摆脱了语法错误一样。但是,在这种情况下,它并不是很有用,因为它认为您使用的“修订”不是实际的修订。
以上是关于当返回语句时,逗号运算符,braced-init-list和std :: unique_ptr合并在一起的主要内容,如果未能解决你的问题,请参考以下文章