简体   繁体   English

如何打印通用 std::list 迭代器?

[英]How to print generic std::list iterator?

I want to be able to print any std::list iterator by printing its value.我希望能够通过打印任何std::list迭代器的值来打印它。 My initial code looked like this:我的初始代码如下所示:

template<typename T>
std::ostream& operator<<(std::ostream& os, const typename std::list<T>::const_iterator& x)
{
   return os << "&" << *x;
}

Which did not work, since the compiler can not determine the parameter T .哪个不起作用,因为编译器无法确定参数T I then tried making it generic over the iterator type itself and using iterator_traits to limit it to iterators.然后,我尝试使其对迭代器类型本身具有通用性,并使用iterator_traits将其限制为迭代器。

template<
    typename It,
    typename = typename std::iterator_traits<It>::value_type
>
std::ostream &operator<<(std::ostream &os, const It &x)
{
    return os << "&" << *x;
}

But then, of course, I get two conflicting implementations for std::ostream << *const char , since pointers are also iterators.但是,当然,我得到两个相互冲突的std::ostream << *const char实现,因为指针也是迭代器。 How can I limit the implementation to std::list iterators so I don't get a conflict?如何将实现限制为std::list迭代器,以免发生冲突?

You can constrain the type as iterator or const_iterator of std::list .您可以将类型限制为std::listiteratorconst_iterator Eg例如

template<typename It>
std::enable_if_t<std::is_same_v<It, typename std::list<typename std::iterator_traits<It>::value_type>::iterator> ||
                 std::is_same_v<It, typename std::list<typename std::iterator_traits<It>::value_type>::const_iterator>
                 , std::ostream &> 
operator<<(std::ostream &os, const It &x) {
    return os << "&" << *x;
}

You can SFINAE the const char* out from the operator<< overload.您可以从operator<<重载中SFINAE const char*

#include <type_traits> // std::enable_if_t, std::is_same_v, std::remove_reference_t

template<
    typename It,
    typename = typename std::iterator_traits<It>::value_type
>
auto operator<<(std::ostream &os, const It &x)
-> std::enable_if_t< !std::is_same_v<std::remove_reference_t<It>, const char*>, std::ostream&>
{
    return os << "&" << *x;
}

( See a Demo ) 见演示

Note that, the above is not only restricted for std::list::iterator , meaning the iterators from the other containers, can also consider this overload.请注意,上述内容不仅限于std::list::iterator ,这意味着来自其他容器的迭代器也可以考虑这种重载。 This might not be the behaviour you want.这可能不是您想要的行为。


Since we could not get the container type from the iterator , I would suggest the same as @super mentioned in the comments.由于我们无法从 iterator 获取容器类型,我建议与评论中提到的@super相同。 Provide a operator<< overload for the Legacy Bidirectional Iterator which is what the std::list has.std::list所具有的Legacy Bidirectional Iterator提供operator<<重载。

Following is an example code, which will work for your expected cases as well as all the containers, which meet the requirements of a bidirectional iterator.以下是一个示例代码,它将适用于您预期的情况以及所有满足双向迭代器要求的容器。

#include <list>
#include <iostream>
#include <iterator>    // std::iterator_traits, std::bidirectional_iterator_tag
#include <type_traits> // std::is_same_v, std::enable_if_t

// SFINAE helper  type for bidirectional_iterator_t
template<typename Iterator, typename ReType = void>
using enable_for_bidirectional_iterator_t
= std::enable_if_t<
   std::is_same_v<std::bidirectional_iterator_tag, typename std::iterator_traits<Iterator>::iterator_category>
   , ReType
>;

template<typename Iterator>
auto operator<<(std::ostream& os, const Iterator x) noexcept
-> enable_for_bidirectional_iterator_t<Iterator, std::ostream&>
{
   return os << "&" << *x;
}

( See a Demo ) 见演示


However, usually, you provide an operator<< overload for the container, not for the iterators.但是,通常,您为容器而不是迭代器提供operator<<重载。 You might want to rethink about the design.您可能需要重新考虑设计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM