У меня есть функция, которая перегружена для многих типов.
Но моя текущая проблема связана с этим (LWS здесь: LWS):
#include <iostream>
#include <string>
#include <sstream>
#include <type_traits>
// First version
template<typename T, class = typename std::enable_if<std::is_fundamental<T>::value>::type>
std::string f(const T& x)
{
return std::to_string(x);
}
// Second version
template<typename... T>
std::string f(const std::tuple<T...>& x)
{
return std::to_string(sizeof...(T)); // It's just an example here
}
// Third version
template<typename T, class = typename std::enable_if<!std::is_fundamental<T>::value>::type, class = void>
std::string f(const T& x)
{
std::ostringstream oss;
oss<<x;
return oss.str();
}
// Main
int main(int argc, char* argv[])
{
std::cout<<f(42)<<std::endl;
std::cout<<f(std::string("Hello World"))<<std::endl;
std::cout<<f(std::tuple<int, int, int, int, int, int>(4, 8, 15, 16, 23, 42))<<std::endl;
return 0;
}
Моя проблема в том, что когда мы звоним f()
для std::tuple
третья версия выполнена, а не вторая.
Как решить эту проблему (решение будет разрешать третью версию только для типов, где <<
определяется, но я не знаю, как это сделать, и если это лучший способ решить проблему)?
Ваша единственная проблема в том, что вы забыли #include <tuple>
, что показано в ошибке на LWS. Вот исправленная версия это правильно компилируется. Вторая перегрузка всегда лучше, чем третья, поскольку она более специализированный согласно частичным правилам заказа.
Если вы все еще хотите знать, как проверить существование функции, которая вызывает SFINAE, если ее там нет, проверьте этот мой ответ на вопрос, посвященный этой теме. 🙂 У него даже есть пример, который в значительной степени соответствует тому, что вы хотите.
Других решений пока нет …