Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eliminate repetition in C++ code?

Tags:

c++

templates

dry

Given the following:

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;
}

is there a way to eliminate repetition? I want to use templates, but I only want it for the following types: const char* int, unsigned, and size_t

like image 386
anon Avatar asked Feb 24 '10 04:02

anon


People also ask

How do I remove a repeating character from a string in C #?

Use Hashset to remove duplicate characters. string myStr = "kkllmmnnoo"; Now, use HashSet to map the string to char. This will remove the duplicate characters from a string.


2 Answers

Really, in "vanilla" C++ you either write the by hand, for specific types, or you use a template like dirkgently suggested.

That said, if you can use Boost this does what you want:

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;
}

This will generate a compile-time error with the message TYPE_NOT_ALLOWED embedded in it if the type being compiled is not contained in the typelist.

Also, since this answer requires Boost I just used lexical_cast. You'll note you're repeating that code, and that's bad. Consider wrapping that functionality into a function.


If you aren't able to use Boost, you can simulate this pretty easily with some type traits:

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;
}

This will also generate a compile-time error if the assert fails, though the code isn't as sexy. :( <- Not sexy

like image 132
GManNickG Avatar answered Oct 03 '22 00:10

GManNickG


Something like this should work:

template <class T>
StreamLogger& operator<<(T val) {
  istringstream s;
  s << val;
  elements.push_back(s.str()); // assuming elements is a vector<string>
  return *this;
}
like image 23
dirkgently Avatar answered Oct 03 '22 01:10

dirkgently