为什么 std::begin 使用尾随 return 类型语法?
Why std::begin uses trailing return type syntax?
范围访问函数 std::begin
声明如下(对于容器):
template< class C >
auto begin( C& c ) -> decltype(c.begin());
我只是想知道为什么不简单
template< class C >
decltype(C::begin) begin( C& c );
这两个有什么区别吗?
等效代码为
template< class C >
decltype(::std::declval<C &>().begin()) begin( C& c );
哪个更长,可能更容易出错。
这个版本
template< class C >
decltype(C::begin) begin( C& c )
不行,因为
decltype(C::begin)
表示方法的类型,不是方法调用结果的类型,反正
begin
方法为标准容器重载,如果没有函数调用的上下文(即使未求值),编译器将无法决定应该参与哪个重载
VTT 显示的 std::declval
版本修复了这个问题,方法是创建一个未评估的函数调用上下文,在该上下文中可以解决重载问题。使用尾随 decltype
可以避免重复参数类型。
范围访问函数 std::begin
声明如下(对于容器):
template< class C >
auto begin( C& c ) -> decltype(c.begin());
我只是想知道为什么不简单
template< class C >
decltype(C::begin) begin( C& c );
这两个有什么区别吗?
等效代码为
template< class C >
decltype(::std::declval<C &>().begin()) begin( C& c );
哪个更长,可能更容易出错。
这个版本
template< class C >
decltype(C::begin) begin( C& c )
不行,因为
decltype(C::begin)
表示方法的类型,不是方法调用结果的类型,反正begin
方法为标准容器重载,如果没有函数调用的上下文(即使未求值),编译器将无法决定应该参与哪个重载
VTT 显示的 std::declval
版本修复了这个问题,方法是创建一个未评估的函数调用上下文,在该上下文中可以解决重载问题。使用尾随 decltype
可以避免重复参数类型。