Я пытаюсь создать служебную функцию ToString
, которая либо вызывает std::to_string
, либо пользовательский метод to_string
, определенный где-то еще. Вот что я придумал для версии 1.0:
Контекст
Код здесь очень близок к тому, с чем я работаю для контекста. У меня есть перечисления из сторонней библиотеки, которые определены с использованием определения C stlye, а также перечисления, которые я определил с использованием стиля C ++.
//From my 3rd party library
namespace ThirdPartyNamespace
{
typedef enum
{
UnscopedValue
} Unscoped;
}
//Defined in Scoped.h
namespace MyNamespace
{
enum class Scoped
{
ScopedValue
};
static std::string to_string(Scoped value)
{
return "Enums::Scoped";
}
}
//Defined in Helpers.h, contains to_string methods for the enums in the 3rd party library
namespace Helpers
{
static std::string to_string(ThirdPartyNamespace::Unscoped value)
{
return "Enums::Unscoped";
}
}
Код вызова
ThirdPartyNamespace::Unscoped x = ThirdPartyNamespace::UnscopedValue;
MyNamespace::Scoped y = MyNamespace::Scoped::ScopedValue;
std::cout << Utilities::ToString(x) << std::endl;
std::cout << Utilities::ToString(y) << std::endl;
Код утилиты
namespace Utilities
{
template <typename T>
std::string ToString(const T& value)
{
using std::to_string;
return to_string(value);
}
}
Это компилируется и работает для Scoped
, но записывает целочисленное значение для Unscoped
. Я провел небольшое исследование, и, похоже, чтобы это исправить, мне нужно было использовать std::enable_if
для моих типов перечислений. После некоторого исследования того, как работает std::enable_if
и SFINAE, я придумал то, что, как я думал, будет работать:
Utility Code
template<typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
static std::string ToString(const T& value)
{
using std::to_string;
return to_string(value);
}
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
static std::string ToString(const T& value)
{
return to_string(value);
}
Однако это не компилируется . В частности, для Unscoped
он выдает ошибку 'to_string': identifier not found
(я подтвердил, что это была ошибка, закомментировав вызов с помощью Unscoped
, и он скомпилировался и работал, как ожидалось).
У меня вопрос: почему компилятор не может найти мой собственный метод to_string
?
Дополнительный вопрос: из моего чтения я обнаружил, что ::type* = nullptr
"устанавливает значение по умолчанию для параметра 'type' шаблона, равное 'nullptr'" ( Source ), что именно означает ли это, и зачем здесь значение по умолчанию?