Traits类从back_insert_iterator中提取容器的value_type

时间:2015-03-15 20:21:54

标签: c++ iterator typetraits value-type inserter

std::back_insert_iterator value_type等于void,但它还有protected成员container,其中包含指向基础Container的指针}。我试图写一个traits类来提取容器的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, "");
}

Live Example

然而,这(或多或少地预期)会遇到不完整的类型错误。反正这是为了获取容器的value_type

2 个答案:

答案 0 :(得分:6)

@Rapptz的答案是正确的,但是对于通用代码(即,当先前不清楚是否处理原始T*back_insert_iterator或其中一个标准库&#39;其他输出迭代器),需要更系统的方法。

为此,在用户定义的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 = char, class traits = std::char_traits<charT>>
struct output_iterator_traits<std::ostream_iterator<T, charT, traits>>
:
        std::iterator<std::output_iterator_tag, T>
{};

template <class charT, class traits = std::char_traits<charT>>
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个输出迭代器,特化继承自std::iterator<std::output_iterator_tag, V> {{1}是作为迭代器V的参数出现的类型。

对于插入迭代器,这对应于operator=(const V&),原始存储迭代器为typename Container::value_typeTostream迭代器为ostreambuf和{分别为{1}}。

表格

的通用算法
T
然后,

将透明地使用原始指针和标准库的输出迭代器。

答案 1 :(得分:2)

您可以使用它拥有的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, "");
}

Live Example