[英]Discarding the output of a function that needs an output iterator
假設在 C++ 中有一個模板 function 做了一些有用的工作,但也通過 output 迭代器輸出一系列值。 現在假設該值序列有時很有趣,但有時沒有用。 Is there a ready-to-use iterator class in the STL that can be instantiated and passed to the function and will ignore any values the function tries to assign to the output iterator? 換句話說,將所有數據發送到 /dev/null?
STL不提供這樣的迭代器。 但你可以自己編寫代碼(測試代碼):
struct null_output_iterator :
std::iterator< std::output_iterator_tag,
null_output_iterator > {
/* no-op assignment */
template<typename T>
void operator=(T const&) { }
null_output_iterator & operator++() {
return *this;
}
null_output_iterator operator++(int) {
return *this;
}
null_output_iterator & operator*() { return *this; }
};
作為operator*
的結果,它不需要使用任何數據。 *it = x;
的結果*it = x;
在輸出迭代器要求中沒有使用,所以我們可以給它一個返回類型的void
。
編輯:讓我們來看看這個operator*
工作原理。 標准在24.1.2 / 1中說明了輸出迭代器的要求,在這兩種情況下:
*it = t;
*it++ = t;
沒有使用這些表達式的結果。 這就是使這項工作的原因:
null_output_iterator it;
*it; // returns a null_output_iterator& per definition of the `operator*`.
*it = some_value; // returns void per definition of the templated `operator=`.
現在我們不需要在operator*
返回任何數據:我們只使用迭代器本身。 請注意,模板化運算符=不會覆蓋內置復制賦值運算符。 它仍然提供。
寫一個並不難。
template<typename T>
class NullOutputIterator
{
public:
NullOutputIterator() {}
NullOutputIterator& operator++() { return *this; }
NullOutputIterator& operator++(int) { return *this; }
T& operator*() { return m; }
T* operator->() { return &m; }
private:
T m;
};
我沒有對此進行測試,可能還有一些重要的缺失,但我認為這是個主意。
你有Boost可用嗎? 如果是這樣,你可以使用一個function_output_iterator包裝的空函數。
但這並不理想。 無論你使用什么迭代器,仍然需要在operator *中為return返回創建一個value_type實例,即使它然后拋出它。
我基於std :: back_insert_iterator ,但沒有容器:
#include <iterator>
template<typename T>
class NullOutputIter
: public std::iterator<std::output_iterator_tag,void,void,void,void>
{
public:
NullOutputIter &operator=(const T &) { return *this; }
NullOutputIter &operator*() { return *this; }
NullOutputIter &operator++() { return *this; }
NullOutputIter operator++(int) { return *this; }
};
這類似於約翰內斯的答案,但沒有模板operator=
取任何東西。 我喜歡強烈的打字; 我想*it = wrong_type_thing
是編譯時錯誤。 此外,對於std::iterator
的各種模板參數,它使用void
,就像標准庫中的輸出迭代std::iterator
一樣。
這也類似於Mark的解決方案,但是(a)它正確地從std::iterator
繼承而且(b)它沒有不需要的內部狀態變量。
對於 C++17,std::iterator 已棄用。 如果要避免警告,則必須在公共接口中聲明類型:
///
/// @brief Allows to discard the output of functions that requires an output iterator
///
template<typename T>
struct null_output_iterator
{
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = T;
using pointer = T*;
using reference = T&;
///
/// @brief No-op assignment
///
void operator=(T const&) {}
///
/// @brief Can be pre-incremented
///
null_output_iterator & operator++()
{
return *this;
}
///
/// @brief Can be post-incremented
///
null_output_iterator operator++(int)
{
return *this;
}
///
/// @brief Can be dereferenced
///
null_output_iterator & operator*()
{
return *this;
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.