Я принимаю это: вы можете взять metafunction, который вы нашли как есть, он работает красиво. Давайте по-прежнему кратко обсудим, почему он работает:
sizeof
фактически не оценивает выражение; он выводит свой тип и возвращает размер этого типа. Типовые размеры определяются реализацией, и мы не можем много думать о них, но мы знаем, что sizeof(char) != sizeof(char[2])
, поэтому мы используем эти типы для тестирования.
Мы определяем оператор потока на уровне пространства имен, используя тип any_t
, который примет - вы догадались - любой тип и пусть он что-то возвращает (на самом деле не важно какой тип, если это не ostream &
). Это то, к чему мы возвращаемся, если тип не имеет определенного оператора потока. В самом классе мы теперь определяем две функции: один принимает ostream &
, что будет результатом, если оператор потока определен, и один принимает тип возвращаемого значения, который мы определили для нашей резервной функции.
Теперь мы можем протестировать sizeof(test(s << c))
, который, опять же, не будет оценивать выражение, определяет только тип возврата и возвращает его размер.
Теперь все, что мы понимаем, как это работает, все, что осталось сделать, это вставить это в наше приложение. Существует несколько подходов к этому; один из способов, который также работает до C++ 11 является использование функтора:
template <bool, typename T>
struct to_string_functor
{
std::string operator()(T const & t) const
{
std::stringstream ss;
ss << t;
return ss.str();
}
};
template <typename T>
struct to_string_functor<false, T>
{
std::string operator()(T const &) const
{
return typeid(T).name();
}
};
template <typename T>
struct foo
{
std::string to_string() const
{
return to_string_functor<
has_insertion_operator<T>::value, T
>()(m_Value);
}
/* ... */
};
Есть несколько способов сделать это, еще один будучи enable_if
, если C++ 11 доступна для вас (вы, вероятно, требуется частично специализированные функции для этого); вы можете прочитать this excellent blog post по этому вопросу.
В этом простом случае, однако, функтор должен делать, на мой взгляд.
Разрешена C++ 11? – nijansen