Устранить повторение в коде C ++? - PullRequest
6 голосов
/ 24 февраля 2010

Учитывая следующее:

StreamLogger& operator<<(const char* s) {
  elements.push_back(String(s));
  return *this;
}

StreamLogger& operator<<(int val) {
  elements.push_back(String(asString<int>(val)));
  return *this;
}

StreamLogger& operator<<(unsigned val) {
  elements.push_back(String(asString<unsigned>(val)));
  return *this;
}

StreamLogger& operator<<(size_t val) {
  elements.push_back(String(asString<size_t>(val)));
  return *this;
}

есть ли способ устранить повторение? Я хочу использовать шаблоны, но я хочу использовать их только для следующих типов: const char * int, unsigned и size_t

Ответы [ 2 ]

6 голосов
/ 24 февраля 2010

Действительно, в «ванильном» 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>

1 голос
/ 24 февраля 2010

Примерно так должно работать:

template <class T>
StreamLogger& operator<<(T val) {
  istringstream s;
  s << val;
  elements.push_back(s.str()); // assuming elements is a vector<string>
  return *this;
}
...