函数模板中的尾随 decltype

Version >= C++ 11

约束函数之一是使用尾随 decltype 来指定返回类型:

namespace details {
   using std::to_string;

   // this one is constrained on being able to call to_string(T)
   template <class T>
   auto convert_to_string(T const& val, int )
       -> decltype(to_string(val))
   {
       return to_string(val);
   }

   // this one is unconstrained, but less preferred due to the ellipsis argument
   template <class T>
   std::string convert_to_string(T const& val, ... )
   {
       std::ostringstream oss;
       oss << val;
       return oss.str();
   }
}

template <class T>
std::string convert_to_string(T const& val)
{
    return details::convert_to_string(val, 0);
}

如果我用一个可以调用 to_string() 的参数调用 convert_to_string(),那么我有两个可行的 details::convert_to_string() 函数。首先是首选,因为从 0int 的转换是比从 0... 的转换更好的隐式转换序列

如果我用一个我无法调用 to_string() 的参数调用 convert_to_string(),那么第一个函数模板实例化会导致替换失败(没有 decltype(to_string(val)))。结果,该候选者从过载集中移除。第二个函数模板是不受约束的,因此它被选中,我们改为通过 operator<<(std::ostream&, T)。如果那个是未定义的,那么我们在线 oss << val 上有一个模板堆栈的硬编译错误。