为什么 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 )

不行,因为

  1. decltype(C::begin)表示方法的类型,不是方法调用结果的类型,反正
  2. begin 方法为标准容器重载,如果没有函数调用的上下文(即使未求值),编译器将无法决定应该参与哪个重载

VTT 显示的 std::declval 版本修复了这个问题,方法是创建一个未评估的函数调用上下文,在该上下文中可以解决重载问题。使用尾随 decltype 可以避免重复参数类型。