6

具有等于​​ ,但它也有一个std::back_insert_iterator持有指向底层的指针的成员。我正在尝试编写一个特征类来提取容器的,如下所示:value_typevoidprotectedcontainerContainervalue_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吗?

4

2 回答 2

9

@Rapptz 的答案是正确的,但对于通用代码(即,当不清楚先验是处理原始T*的还是back_insert_iterator标准库的其他输出迭代器之一时),需要一种更系统的方法。

为此,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 个输出迭代器,特化继承自std::iterator<std::output_iterator_tag, V>whereV是作为迭代器的参数出现的类型operator=(const V&)

对于插入迭代器,这对应于typename Container::value_type, 对于原始存储迭代器到T, 和 forostreamostreambuf迭代器到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 */ };
     }
}

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

于 2015-03-16T19:02:51.413 回答
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, "");
}

现场示例

于 2015-03-15T20:28:12.127 回答