use*_*570 5 c++ casting void c++11 c++17
void我正在学习 C++ 中的模板,并遇到了一个使用强制转换的示例:
template<typename T>
auto func (T const& t) -> decltype( (void)(t.size()), T::size_type() )
{
return t.size();
}
Run Code Online (Sandbox Code Playgroud)
解释中写道:
将表达式强制转换为 void 是为了避免用户定义的逗号运算符针对表达式类型重载的可能性。
我的问题是:
如何使用强制转换为 void 来“避免用户定义的逗号运算符重载表达式类型的可能性”?我的意思是,任何人都可以举出任何例子,如果我们不使用void此代码会给出错误吗?例如,假设我们有一个名为 的类SomeClass,它重载了逗号运算符。现在,如果我们不使用,这会成为问题吗void?
static_cast在这种情况下可以使用 C 风格的强制转换吗?例如,类似的东西static_cast<void>(t.size())。我正在阅读使用 C++17 功能的示例,因此我想知道为什么作者在这种情况下使用了 C 风格转换。
我读过强制转换为“void”到底有什么作用?,从中我得到的印象是,如果我们使用(void)xthen 这意味着抑制编译器警告,并且还意味着“忽略 x 的值”。但后来我无法理解表达式x和之间的区别(void)x。
考虑这种病理类型:
struct foo {
struct size_type {
bool operator,(size_type) { return false;}
};
size_type size() { return {};}
};
Run Code Online (Sandbox Code Playgroud)
它确实有一个size_type并且它确实有一个size()方法。但是,如果没有强制转换为void,模板将无法推导出正确的返回类型,decltype( (t.size()), typename T::size_type() )因为bool:
#include <type_traits>
template<typename T>
auto func (T const& t) -> decltype( (t.size()), typename T::size_type() )
{
return t.size();
}
struct foo {
struct size_type {
bool operator,(size_type) { return false;}
};
size_type size() const { return {};}
};
int main()
{
func(foo{});
}
Run Code Online (Sandbox Code Playgroud)
结果错误:
<source>:6:8: error: no viable conversion from returned value of type 'foo::size_type' to function return type 'decltype((t.size()) , typename foo::size_type())' (aka 'bool')
return t.size();
^~~~~~~~
<source>:20:4: note: in instantiation of function template specialization 'func<foo>' requested here
func(foo{});
^
1 error generated.
ASM generation compiler returned: 1
<source>:6:8: error: no viable conversion from returned value of type 'foo::size_type' to function return type 'decltype((t.size()) , typename foo::size_type())' (aka 'bool')
return t.size();
^~~~~~~~
<source>:20:4: note: in instantiation of function template specialization 'func<foo>' requested here
func(foo{});
^
Run Code Online (Sandbox Code Playgroud)
static_cast可以用A. 然而,由于实际上没有任何东西被转换(它是一个未评估的上下文),所以 c 风格的转换不会造成太大的伤害。void请注意如何通过使用对用户定义的强制转换operator,来绕过并推导出正确的返回类型: https: //godbolt.org/z/jozx1YGWr。这是因为使用了其结果与 类型相同的void, whatever内置函数。您不能使用用户定义的覆盖;没有有效的语法。operator,whatevervoid, whateveroperator,
我认为代码只是为了说明这一效果,因为即使转换为void1 也可以弥补其他失败的示例(例如,模板没有显式测试t.size()实际返回T::size_type)。
另请参阅此处有关“很少重载的运算符”的部分:
逗号运算符,
operator,. 与内置版本不同,重载不会将左操作数排在右操作数之前。(C++17 之前)由于此运算符可能会重载,因此泛型库使用诸如a,void(),b代替之类的表达式a,b来顺序执行用户定义类型的表达式。boost 库用于operator,boost.assign、boost.spirit 和其他库。数据库访问库 SOCI 也超载operator,。
| 归档时间: |
|
| 查看次数: |
262 次 |
| 最近记录: |