函式模板中的尾隨 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 上有一個模板堆疊的硬編譯錯誤。