Действительно, в «ванильном» C ++ вы либо пишете от руки, для конкретных типов, либо используете шаблон, как предложено непосредственно.
Тем не менее, если вы можете использовать Boost, это делает то, что вы хотите:
template <class T>
StreamLogger& operator<<(T val)
{
typedef boost::mpl::vector<const char*, int,
unsigned, size_t> allowed_types;
BOOST_MPL_ASSERT_MSG(boost::mpl::contains<allowed_types, T>::value,
TYPE_NOT_ALLOWED, allowed_types);
// generic implementation follows
elements.push_back(boost::lexical_cast<std::string>(val));
return *this;
}
Это приведет к ошибке времени компиляции с вложенным в нее сообщением TYPE_NOT_ALLOWED
, если компилируемый тип не содержится в списке типов.
Кроме того, поскольку для ответа требуется Boost, я только что использовал lexical_cast
. Вы заметите, что повторяете этот код, и это плохо. Рассмотрим упаковку этой функциональности в функцию.
Если вы не не можете использовать Boost, вы можете довольно легко смоделировать это с некоторыми чертами типа:
template <typename T, typename U>
struct is_same
{
static const bool value = false;
};
template <typename T>
struct is_same<T, T>
{
static const bool value = true;
};
template <bool>
struct static_assert;
template <>
struct static_assert<true> {}; // only true is defined
// not the best, but it works
#define STATIC_ASSERT(x) static_assert< (x) > _static_assert_
template <class T>
StreamLogger& operator<<(T val)
{
STATIC_ASSERT(is_same<const char*, T>::value ||
is_same<int, T>::value ||
is_same<unsigned, T>::value ||
is_same<size_t, T>::value);
// generic implementation follows
elements.push_back(boost::lexical_cast<std::string>(val));
return *this;
}
Это также сгенерирует ошибку во время компиляции, если утверждение не выполнено, хотя код не такой сексуальный. :( <- Не сексуально </p>