【问题标题】:Eliminate repetition in C++ code?消除 C++ 代码中的重复?
【发布时间】:2010-02-24 04:52:54
【问题描述】:

鉴于以下情况:

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

【问题讨论】:

  • @anon:您是只希望这些类型使用它还是其他类型也可以使用它?换句话说,如果你尝试使用其他类型会发生什么?编译器错误或无操作或 push_back() 进入向量?
  • @Clifford:但没有一个比我的解决方案更性感。 :)
  • @Naveen:仅适用于那些类型;这就是我不想使用通用模板的原因。
  • @GMan:这就是我没有投票结束的原因。仅供参考。

标签: c++ templates dry


【解决方案1】:

真的,在“vanilla”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。您会注意到您正在重复该代码,这很糟糕。考虑将wrapping 该功能整合到一个函数中。


如果你不能使用 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;
}

如果断言失败,这也会产生编译时错误,尽管代码没有那么性感。 :(

【讨论】:

  • 不幸的是,编译器错误可能也不性感:)
【解决方案2】:

这样的事情应该可以工作:

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

【讨论】:

  • 但 OP 只希望它用于特定类型。
  • @Naveen:不确定他是否想要一个受限制的模板,或者那些是他需要的 only 类型。一些澄清会有所帮助。
  • @*:FWIW,可以使用 Boost.Type Traits 和 BOOST_STATIC_ASSERT 来检查特定类型。
猜你喜欢
  • 2013-01-30
  • 2012-07-05
  • 1970-01-01
  • 1970-01-01
  • 2018-08-25
  • 1970-01-01
  • 2011-04-02
  • 2011-01-12
  • 1970-01-01
相关资源
最近更新 更多