簡體   English   中英

Traits類從back_insert_iterator中提取容器的value_type

[英]Traits class to extract container's value_type from a back_insert_iterator

std::back_insert_iterator value_type等於void ,但它也有一個protected成員container ,該container包含指向基礎Container的指針。 我正在嘗試編寫一個特征類來提取容器的value_type ,方法如下:

#include <iterator>
#include <type_traits>
#include <vector>

template<class OutputIt>
struct outit_vt
:
    OutputIt
{
    using self_type = outit_vt<OutputIt>;
    using value_type = typename std::remove_pointer_t<decltype(std::declval<self_type>().container)>::value_type;
};

int main()
{
    std::vector<int> v;
    auto it = std::back_inserter(v);
    static_assert(std::is_same<outit_vt<decltype(it)>::value_type, int>::value, "");
}

現場例子

但是,這(或多或少地)會遇到不完整的類型錯誤。 無論如何,為了提取容器的value_type是否有解決辦法?

@Rapptz的答案是正確的,但對於通用代碼(即,如果不清楚先驗是先處理原始T*還是back_insert_iterator還是標准庫的其他輸出迭代器之一),則需要一種更系統的方法。

為此,在用戶定義的namespace xstd中的類模板output_iterator_traits的定義namespace xstd

#include <iterator>             // iterator, iterator_traits, input_iterator_tag, output_iterator_tag, random_access_iterator_tag
                                // back_insert_iterator, front_insert_iterator, insert_iterator, ostream_iterator, ostreambuf_iterator
#include <memory>               // raw_storage_iterator

namespace xstd {

template<class T>
struct output_iterator_traits
:
        std::iterator_traits<T>
{};

template< class OutputIt, class T>
struct output_iterator_traits<std::raw_storage_iterator<OutputIt, T>>
:
        std::iterator<std::output_iterator_tag, T>
{};

template<class Container>
struct output_iterator_traits<std::back_insert_iterator<Container>>
:
        std::iterator<std::output_iterator_tag, typename Container::value_type>
{};

template<class Container>
struct output_iterator_traits<std::front_insert_iterator<Container>>
:
        std::iterator<std::output_iterator_tag, typename Container::value_type>
{};

template<class Container>
struct output_iterator_traits<std::insert_iterator<Container>>
:
        std::iterator<std::output_iterator_tag, typename Container::value_type>
{};

template <class T, class charT, class traits>
struct output_iterator_traits<std::ostream_iterator<T, charT, traits>>
:
        std::iterator<std::output_iterator_tag, T>
{};

template <class charT, class traits>
struct output_iterator_traits<std::ostreambuf_iterator<charT, traits>>
:
        std::iterator<std::output_iterator_tag, charT>
{};

} // namespace xstd

非專業版本僅繼承自std::iterator_traits<T> ,但是對於<iterator><memory>標頭中定義的6個輸出迭代<iterator> ,專業化繼承自std::iterator<std::output_iterator_tag, V> ,其中V是作為迭代器的operator=(const V&)的參數出現的類型。

對於插入迭代器,這分別對應於typename Container::value_type ,對於原始存儲迭代器為T ,對於ostreamostreambuf迭代器分別為TcharT

形式的通用算法

template<class InputIt, class OutputIt>
auto my_fancy_algorithm(InputIt first, InputIt last, OutputIt dest)
{
     using T = typename xstd::output_iterator_traits<OutputIt>::value_type;
     for (; first != last; ++first) {
         // ... construct arguments from *first
         *dest++ = T{ /* arguments */ };
     }
}

然后將透明地使用原始指針和標准庫的輸出迭代器。

您可以只使用它具有的container_type

#include <iterator>
#include <type_traits>
#include <vector>

template<typename T>
struct outit_v {
    using container_type = typename T::container_type;
    using value_type = typename container_type::value_type;
};

int main()
{
    std::vector<int> v;
    auto it = std::back_inserter(v);
    static_assert(std::is_same<outit_v<decltype(it)>::value_type, int>::value, "");
}

現場例子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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