簡體   English   中英

丟棄需要 output 迭代器的 function 的 output

[英]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)它沒有不需要的內部狀態變量。

更新答案 (2022)

對於 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM