我目前已经拥有并运行了这段代码:
我希望通过以下方式使其更加紧凑和易读:
当然,这还是很初步的,但它应该能够给出思路。有了上述的适配器,我接下来可以编写以下代码:
如果标准包括这样的适配器,我会使用它,因为这意味着它是无缺陷的,但由于情况并非如此,我可能会保持我的循环不变。
这样的适配器将允许重用现有算法,并以不同的方式进行混合,这是今天不可能的,但它也可能有缺点,我可能目前正在忽视...
string word="test,";
string::iterator it = word.begin();
for (; it != word.end(); it++)
{
if (!isalpha(*it)) {
break;
}
else {
*it = toupper(*it);
}
}
word.erase(it, word.end());
// word should now be: TEST
我希望通过以下方式使其更加紧凑和易读:
- 组合现有的标准C++算法(*)
- 仅执行一次循环
(*) 我假设组合现有的算法可以使我的代码更易读...
另一种解决方案
除了像jrok建议的定义自定义transform_until
算法之外,还可以定义一个自定义迭代器适配器,该适配器使用基础迭代器进行迭代,但在返回之前通过修改基础引用来重新定义operator*()。类似这样:
template <typename Iterator, typename UnaryFunction = typename Iterator::value_type (*)(typename Iterator::value_type)>
class sidefx_iterator: public std::iterator<
typename std::forward_iterator_tag,
typename std::iterator_traits<Iterator>::value_type,
typename std::iterator_traits<Iterator>::difference_type,
typename std::iterator_traits<Iterator>::pointer,
typename std::iterator_traits<Iterator>::reference >
{
public:
explicit sidefx_iterator(Iterator x, UnaryFunction fx) : current_(x), fx_(fx) {}
typename Iterator::reference operator*() const { *current_ = fx_(*current_); return *current_; }
typename Iterator::pointer operator->() const { return current_.operator->(); }
Iterator& operator++() { return ++current_; }
Iterator& operator++(int) { return current_++; }
bool operator==(const sidefx_iterator<Iterator>& other) const { return current_ == other.current_; }
bool operator==(const Iterator& other) const { return current_ == other; }
bool operator!=(const sidefx_iterator<Iterator>& other) const { return current_ != other.current_; }
bool operator!=(const Iterator& other) const { return current_ != other; }
operator Iterator() const { return current_; }
private:
Iterator current_;
UnaryFunction fx_;
};
当然,这还是很初步的,但它应该能够给出思路。有了上述的适配器,我接下来可以编写以下代码:
word.erase(std::find_if(it, it_end, std::not1(std::ref(::isalpha))), word.end());
预先定义以下内容(可通过一些模板魔法简化):
using TransformIterator = sidefx_iterator<typename std::string::iterator>;
TransformIterator it(word.begin(), reinterpret_cast<typename std::string::value_type(*)(typename std::string::value_type)>(static_cast<int(*)(int)>(std::toupper)));
TransformIterator it_end(word.end(), nullptr);
如果标准包括这样的适配器,我会使用它,因为这意味着它是无缺陷的,但由于情况并非如此,我可能会保持我的循环不变。
这样的适配器将允许重用现有算法,并以不同的方式进行混合,这是今天不可能的,但它也可能有缺点,我可能目前正在忽视...
!isalpha(*it)
的过早退出是我唯一可能阻止你实现你所追求的目标的事情,而且老实说,任何可能做到这一点的方法(我一眼看不出来有什么)都很复杂,会让你的清晰度降低。 我建议你还是坚持现在的做法。 - WhozCraigboost::transform_iterator
是我正在寻找的最接近的东西。这种用例将被“副作用”迭代器适配器所覆盖,类似于这样使用:word.erase(std::find_if(sidefx_iterator(word.begin(), ::toupper), word.end(), std::not1(::isalpha)), word.end());
- José Mari