扩展 boost::filtered 的迭代器以支持 operator+ 重载
Extending iterator of boost::filtered to support operator+ overload
我想向 boost::filter_iterator
添加一个 operator+
重载,如下例所示。但是,我在将模板参数解析为 operator+ 重载函数时遇到错误。
#include <iostream>
#include <vector>
#include <boost/range/adaptor/filtered.hpp>
template <typename TPredicate, typename TRange>
class Filtered_Range : public boost::filtered_range<TPredicate, TRange>
{
public:
Filtered_Range(TPredicate Predicate, TRange& Range) : boost::filtered_range<TPredicate, TRange>(Predicate, Range) {}
size_t size() const { return std::distance(this->begin(), this->end()); }
auto operator[](size_t Index) const
{
assert(Index < this->size());
auto It = this->begin();
std::advance(It, Index);
return *It;
}
};
template<typename TPredicate, typename TRange>
typename Filtered_Range<TPredicate, TRange>::filter_iterator&
operator+(typename
Filtered_Range<TPredicate, TRange>::filter_iterator& f, int32_t x ) {
std::cout << "Custom overload\n";
return std::advance(f, x);
}
int main() {
const std::vector<int> nums{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto even_only_custom = Filtered_Range([] (auto n) { return (n % 2 == 0); }, nums);
auto x = even_only_custom.begin();
std::cout << "First Value = " << *(x) << "\n";
std::cout << "Second Value = " << *(x + 1); //error here
}
GCC 11.2 错误信息
<source>: In function 'int main()':
<source>:47:43: error: no match for 'operator+' (operand types are 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' and 'int')
47 | std::cout << "Second Value = " << *(x + 1);
| ~ ^ ~
| | |
| | int
| boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >
<source>:28:1: note: candidate: 'template<class TPredicate, class TRange> typename Filtered_Range<TPredicate, TRange>::filter_iterator& operator+(typename Filtered_Range<TPredicate, TRange>::filter_iterator&, int32_t)'
28 | operator+(typename
| ^~~~~~~~
<source>:28:1: note: template argument deduction/substitution failed:
<source>:47:45: note: couldn't deduce template parameter 'TPredicate'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_algobase.h:67,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/char_traits.h:39,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:568:5: note: candidate: 'template<class _Iterator> constexpr std::reverse_iterator<_Iterator> std::operator+(typename std::reverse_iterator<_Iterator>::difference_type, const std::reverse_iterator<_Iterator>&)'
568 | operator+(typename reverse_iterator<_Iterator>::difference_type __n,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:568:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const std::reverse_iterator<_Iterator>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_algobase.h:67,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/char_traits.h:39,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:1646:5: note: candidate: 'template<class _Iterator> constexpr std::move_iterator<_IteratorL> std::operator+(typename std::move_iterator<_IteratorL>::difference_type, const std::move_iterator<_IteratorL>&)'
1646 | operator+(typename move_iterator<_Iterator>::difference_type __n,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:1646:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const std::move_iterator<_IteratorL>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6094:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
6094 | operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6094:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:56,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:1169:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const _CharT*, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
1169 | operator+(const _CharT* __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:1169:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const _CharT*' and 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:56,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:1189:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(_CharT, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
1189 | operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:1189:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6131:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&, const _CharT*)'
6131 | operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6131:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6147:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&, _CharT)'
6147 | operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6147:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6159:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
6159 | operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6159:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6165:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&, std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&)'
6165 | operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6165:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6171:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&)'
6171 | operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6171:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6193:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const _CharT*, std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&)'
6193 | operator+(const _CharT* __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6193:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const _CharT*' and 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6199:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(_CharT, std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&)'
6199 | operator+(_CharT __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6199:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6205:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, const _CharT*)'
6205 | operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6205:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6211:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, _CharT)'
6211 | operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6211:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_algobase.h:67,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/char_traits.h:39,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:1242:5: note: candidate: 'template<class _Iterator, class _Container> __gnu_cxx::__normal_iterator<_Iterator, _Container> __gnu_cxx::operator+(typename __gnu_cxx::__normal_iterator<_Iterator, _Container>::difference_type, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&)'
1242 | operator+(typename __normal_iterator<_Iterator, _Container>::difference_type
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:1242:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const __gnu_cxx::__normal_iterator<_Iterator, _Container>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/libs/boost_1_67_0/boost/range/iterator_range_core.hpp:27,
from /opt/compiler-explorer/libs/boost_1_67_0/boost/range/iterator_range.hpp:13,
from /opt/compiler-explorer/libs/boost_1_67_0/boost/range/adaptor/filtered.hpp:16,
from <source>:3:
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:955:3: note: candidate: 'template<class Derived, class V, class TC, class R, class D> typename boost::iterators::enable_if<boost::iterators::detail::is_traversal_at_least<TC, boost::iterators::random_access_traversal_tag>, Derived>::type boost::iterators::operator+(const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>&, typename Derived::difference_type)'
955 | BOOST_ITERATOR_FACADE_PLUS((
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:955:3: note: template argument deduction/substitution failed:
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp: In substitution of 'template<class Derived, class V, class TC, class R, class D> typename boost::iterators::enable_if<boost::iterators::detail::is_traversal_at_least<TC, boost::iterators::random_access_traversal_tag>, Derived>::type boost::iterators::operator+(const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>&, typename Derived::difference_type) [with Derived = boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >; V = int; TC = boost::iterators::bidirectional_traversal_tag; R = const int&; D = long int]':
<source>:47:45: required from here
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:955:3: error: no type named 'type' in 'struct boost::iterators::enable_if<boost::iterators::detail::is_traversal_at_least<boost::iterators::bidirectional_traversal_tag, boost::iterators::random_access_traversal_tag>, boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > > >'
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:960:3: note: candidate: 'template<class Derived, class V, class TC, class R, class D> typename boost::iterators::enable_if<boost::iterators::detail::is_traversal_at_least<TC, boost::iterators::random_access_traversal_tag>, Derived>::type boost::iterators::operator+(typename Derived::difference_type, const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>&)'
960 | BOOST_ITERATOR_FACADE_PLUS((
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:960:3: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
Execution build compiler returned: 1
任何关于错误的指示和可能的解决方案将不胜感激。
谢谢!
在
template <typename T>
void foo(typename T::nested_type) {}
T 在 non-deduced context¹ 中。这意味着唯一可以让它工作的方法是使用 SFINAE。
namespace detail {
template <typename T> struct is_filt_it : std::false_type { };
template <typename... Args>
struct is_filt_it<boost::filter_iterator<Args...>> : std::true_type { };
} // namespace detail
template <typename It>
static decltype(auto) operator+(It it, std::enable_if_t<detail::is_filt_it<It>::value, int32_t> x)
{
return std::next(it, x);
}
现在重载始终参与,但因 non-filter_iterator 个参数被 SFINAE 丢弃:
#undef NDEBUG
#include <boost/range/adaptor/filtered.hpp>
#include <iostream>
#include <vector>
template <typename TPredicate, typename TRange>
struct Filtered_Range : boost::filtered_range<TPredicate, TRange> {
using base_type = boost::filtered_range<TPredicate, TRange>;
using base_type::base_type;
auto operator[](size_t i) const {
assert(i < this->size());
return *std::next(base_type::begin(), i);
}
};
template <typename TPredicate, typename TRange>
Filtered_Range(TPredicate const&, TRange const&) -> Filtered_Range<TPredicate, TRange>;
namespace detail {
template <typename T> struct is_filt_it : std::false_type { };
template <typename... Args>
struct is_filt_it<boost::filter_iterator<Args...>> : std::true_type { };
} // namespace detail
template <typename It>
static decltype(auto) operator+(It it, std::enable_if_t<detail::is_filt_it<It>::value, int32_t> x)
{
return std::next(it, x);
}
int main() {
std::vector nums{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto evens = Filtered_Range([](auto n) { return (n % 2 == 0); }, nums);
auto it = evens.begin();
std::cout << "First Value = " << *(it) << "\n";
std::cout << "Second Value = " << *(it + 1) << "\n";
}
版画
First Value = 2
Second Value = 4
¹ 另见例如What is a nondeduced context?
控制实例化
要限制 operator+
仅支持自定义范围子类,您必须使迭代器类型可区分。
“累人”的方法是 subclass/wrap 迭代器并委托所有范围接口来使用它们。
“有线”方式将包装 Predicate(它显示为 filter_iterator 类型的第一个模板参数!)。这样我们就可以查看 filter_iterator 的参数“内部”,以检测谓词何时被适当地“标记”。
尝试 #1(天真)
namespace MyLib {
template <typename F> struct Tagged : F {
Tagged(F f) : F(std::move(f)) {}
using F::operator();
};
} // namespace MyLib
现在,我们在自定义子类中装饰 TPredicate:
template <typename TPredicate, typename TRange>
struct Filtered_Range : boost::filtered_range<MyLib::Tagged<TPredicate>, TRange> {
using base_type = boost::filtered_range<MyLib::Tagged<TPredicate>, TRange>;
using base_type::base_type;
auto operator[](size_t i) const {
assert(i < this->size());
return *std::next(base_type::begin(), i);
}
using const_iterator = typename boost::range_iterator<base_type, void>::type;
};
并且我们扩展 is_filt_it
特性来检查 Tagged<>
谓词:
namespace detail {
template <typename T> struct is_tagged : std::false_type { };
template <typename F> struct is_tagged<MyLib::Tagged<F>> : std::true_type { };
template <typename T, typename = void> struct is_filt_it : std::false_type { };
template <typename F, typename... Args>
struct is_filt_it<boost::filter_iterator<F, Args...>,
std::enable_if_t<is_tagged<F>::value>> : std::true_type {
};
} // namespace detail
遗憾的是,这中断了:
Candidate template ignored: requirement 'detail::is_filt_it<boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<MyLib::Tagged<...>, bool>...
如您所见,Boost 已经 有 包装器(至少有时)并且它打破了我们的检测
尝试 #2(银河大脑)
那么我们是否会变得乏味并更改实际的迭代器类型?
没有! C++ 中有一个有时有点毒的特性:参数相关查找。 ADL 旨在引入“关联的命名空间”以供查找。事实证明,声明在模板参数(及其模板参数)中命名的类型的命名空间被认为是“关联的”。
所以:
namespace MyLib {
namespace AdlBarrier {
template <typename F> struct Tagged : F {
Tagged(F f) : F(std::move(f)) {}
using F::operator();
};
template <typename T> constexpr bool is_tagged(T&&) { return true; }
} // namespace AdlBarrier
using AdlBarrier::Tagged;
} // namespace MyLib
Filtered_Range
没有变化,并且:
namespace detail {
template <typename T, typename = void> struct is_filt_it : std::false_type { };
template <typename F, typename... Args>
struct is_filt_it<boost::filter_iterator<F, Args...>,
std::enable_if_t<is_tagged(static_cast<F*>(nullptr))>>
: std::true_type {
};
} // namespace detail
现在,您可以对自定义范围内的迭代器进行特殊处理:
{
auto evens = Filtered_Range([](auto n) { return (n % 2 == 0); }, nums);
auto it = evens.begin();
std::cout << "First Value = " << *(it) << "\n";
std::cout << "Second Value = " << *(it + 1) << "\n";
}
但是普通香草 boost::filtered_range
没有得到特殊待遇:
{
auto odds = boost::filtered_range([](auto n) { return (n % 2 == 1); }, nums);
auto it = odds.begin();
std::cout << "First Value = " << *(it) << "\n";
std::cout << "Second Value = " << *(it + 1) << "\n"; // doesn't compile
}
现场观看:https://godbolt.org/z/xhqjqa3Gc (or correctly not-compiling: https://godbolt.org/z/67vP6TEGc)
我想向 boost::filter_iterator
添加一个 operator+
重载,如下例所示。但是,我在将模板参数解析为 operator+ 重载函数时遇到错误。
#include <iostream>
#include <vector>
#include <boost/range/adaptor/filtered.hpp>
template <typename TPredicate, typename TRange>
class Filtered_Range : public boost::filtered_range<TPredicate, TRange>
{
public:
Filtered_Range(TPredicate Predicate, TRange& Range) : boost::filtered_range<TPredicate, TRange>(Predicate, Range) {}
size_t size() const { return std::distance(this->begin(), this->end()); }
auto operator[](size_t Index) const
{
assert(Index < this->size());
auto It = this->begin();
std::advance(It, Index);
return *It;
}
};
template<typename TPredicate, typename TRange>
typename Filtered_Range<TPredicate, TRange>::filter_iterator&
operator+(typename
Filtered_Range<TPredicate, TRange>::filter_iterator& f, int32_t x ) {
std::cout << "Custom overload\n";
return std::advance(f, x);
}
int main() {
const std::vector<int> nums{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto even_only_custom = Filtered_Range([] (auto n) { return (n % 2 == 0); }, nums);
auto x = even_only_custom.begin();
std::cout << "First Value = " << *(x) << "\n";
std::cout << "Second Value = " << *(x + 1); //error here
}
GCC 11.2 错误信息
<source>: In function 'int main()':
<source>:47:43: error: no match for 'operator+' (operand types are 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' and 'int')
47 | std::cout << "Second Value = " << *(x + 1);
| ~ ^ ~
| | |
| | int
| boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >
<source>:28:1: note: candidate: 'template<class TPredicate, class TRange> typename Filtered_Range<TPredicate, TRange>::filter_iterator& operator+(typename Filtered_Range<TPredicate, TRange>::filter_iterator&, int32_t)'
28 | operator+(typename
| ^~~~~~~~
<source>:28:1: note: template argument deduction/substitution failed:
<source>:47:45: note: couldn't deduce template parameter 'TPredicate'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_algobase.h:67,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/char_traits.h:39,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:568:5: note: candidate: 'template<class _Iterator> constexpr std::reverse_iterator<_Iterator> std::operator+(typename std::reverse_iterator<_Iterator>::difference_type, const std::reverse_iterator<_Iterator>&)'
568 | operator+(typename reverse_iterator<_Iterator>::difference_type __n,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:568:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const std::reverse_iterator<_Iterator>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_algobase.h:67,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/char_traits.h:39,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:1646:5: note: candidate: 'template<class _Iterator> constexpr std::move_iterator<_IteratorL> std::operator+(typename std::move_iterator<_IteratorL>::difference_type, const std::move_iterator<_IteratorL>&)'
1646 | operator+(typename move_iterator<_Iterator>::difference_type __n,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:1646:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const std::move_iterator<_IteratorL>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6094:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
6094 | operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6094:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:56,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:1169:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const _CharT*, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
1169 | operator+(const _CharT* __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:1169:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const _CharT*' and 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:56,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:1189:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(_CharT, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
1189 | operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.tcc:1189:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6131:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&, const _CharT*)'
6131 | operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6131:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6147:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&, _CharT)'
6147 | operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6147:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6159:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
6159 | operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6159:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6165:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&, std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&)'
6165 | operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6165:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6171:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&)'
6171 | operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6171:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6193:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(const _CharT*, std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&)'
6193 | operator+(const _CharT* __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6193:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const _CharT*' and 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6199:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(_CharT, std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&)'
6199 | operator+(_CharT __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6199:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6205:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, const _CharT*)'
6205 | operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6205:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/string:55,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:42,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6211:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, _CharT)'
6211 | operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/basic_string.h:6211:5: note: template argument deduction/substitution failed:
<source>:47:45: note: 'boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >' is not derived from 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_algobase.h:67,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/char_traits.h:39,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ios:40,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ostream:38,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:1242:5: note: candidate: 'template<class _Iterator, class _Container> __gnu_cxx::__normal_iterator<_Iterator, _Container> __gnu_cxx::operator+(typename __gnu_cxx::__normal_iterator<_Iterator, _Container>::difference_type, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&)'
1242 | operator+(typename __normal_iterator<_Iterator, _Container>::difference_type
| ^~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_iterator.h:1242:5: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const __gnu_cxx::__normal_iterator<_Iterator, _Container>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
In file included from /opt/compiler-explorer/libs/boost_1_67_0/boost/range/iterator_range_core.hpp:27,
from /opt/compiler-explorer/libs/boost_1_67_0/boost/range/iterator_range.hpp:13,
from /opt/compiler-explorer/libs/boost_1_67_0/boost/range/adaptor/filtered.hpp:16,
from <source>:3:
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:955:3: note: candidate: 'template<class Derived, class V, class TC, class R, class D> typename boost::iterators::enable_if<boost::iterators::detail::is_traversal_at_least<TC, boost::iterators::random_access_traversal_tag>, Derived>::type boost::iterators::operator+(const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>&, typename Derived::difference_type)'
955 | BOOST_ITERATOR_FACADE_PLUS((
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:955:3: note: template argument deduction/substitution failed:
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp: In substitution of 'template<class Derived, class V, class TC, class R, class D> typename boost::iterators::enable_if<boost::iterators::detail::is_traversal_at_least<TC, boost::iterators::random_access_traversal_tag>, Derived>::type boost::iterators::operator+(const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>&, typename Derived::difference_type) [with Derived = boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > >; V = int; TC = boost::iterators::bidirectional_traversal_tag; R = const int&; D = long int]':
<source>:47:45: required from here
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:955:3: error: no type named 'type' in 'struct boost::iterators::enable_if<boost::iterators::detail::is_traversal_at_least<boost::iterators::bidirectional_traversal_tag, boost::iterators::random_access_traversal_tag>, boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main()::<lambda(auto:2)>, bool>, __gnu_cxx::__normal_iterator<const int*, std::vector<int> > > >'
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:960:3: note: candidate: 'template<class Derived, class V, class TC, class R, class D> typename boost::iterators::enable_if<boost::iterators::detail::is_traversal_at_least<TC, boost::iterators::random_access_traversal_tag>, Derived>::type boost::iterators::operator+(typename Derived::difference_type, const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>&)'
960 | BOOST_ITERATOR_FACADE_PLUS((
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_67_0/boost/iterator/iterator_facade.hpp:960:3: note: template argument deduction/substitution failed:
<source>:47:45: note: mismatched types 'const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>' and 'int'
47 | std::cout << "Second Value = " << *(x + 1);
| ^
Execution build compiler returned: 1
任何关于错误的指示和可能的解决方案将不胜感激。 谢谢!
在
template <typename T>
void foo(typename T::nested_type) {}
T 在 non-deduced context¹ 中。这意味着唯一可以让它工作的方法是使用 SFINAE。
namespace detail {
template <typename T> struct is_filt_it : std::false_type { };
template <typename... Args>
struct is_filt_it<boost::filter_iterator<Args...>> : std::true_type { };
} // namespace detail
template <typename It>
static decltype(auto) operator+(It it, std::enable_if_t<detail::is_filt_it<It>::value, int32_t> x)
{
return std::next(it, x);
}
现在重载始终参与,但因 non-filter_iterator 个参数被 SFINAE 丢弃:
#undef NDEBUG
#include <boost/range/adaptor/filtered.hpp>
#include <iostream>
#include <vector>
template <typename TPredicate, typename TRange>
struct Filtered_Range : boost::filtered_range<TPredicate, TRange> {
using base_type = boost::filtered_range<TPredicate, TRange>;
using base_type::base_type;
auto operator[](size_t i) const {
assert(i < this->size());
return *std::next(base_type::begin(), i);
}
};
template <typename TPredicate, typename TRange>
Filtered_Range(TPredicate const&, TRange const&) -> Filtered_Range<TPredicate, TRange>;
namespace detail {
template <typename T> struct is_filt_it : std::false_type { };
template <typename... Args>
struct is_filt_it<boost::filter_iterator<Args...>> : std::true_type { };
} // namespace detail
template <typename It>
static decltype(auto) operator+(It it, std::enable_if_t<detail::is_filt_it<It>::value, int32_t> x)
{
return std::next(it, x);
}
int main() {
std::vector nums{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto evens = Filtered_Range([](auto n) { return (n % 2 == 0); }, nums);
auto it = evens.begin();
std::cout << "First Value = " << *(it) << "\n";
std::cout << "Second Value = " << *(it + 1) << "\n";
}
版画
First Value = 2
Second Value = 4
¹ 另见例如What is a nondeduced context?
控制实例化
要限制 operator+
仅支持自定义范围子类,您必须使迭代器类型可区分。
“累人”的方法是 subclass/wrap 迭代器并委托所有范围接口来使用它们。
“有线”方式将包装 Predicate(它显示为 filter_iterator 类型的第一个模板参数!)。这样我们就可以查看 filter_iterator 的参数“内部”,以检测谓词何时被适当地“标记”。
尝试 #1(天真)
namespace MyLib {
template <typename F> struct Tagged : F {
Tagged(F f) : F(std::move(f)) {}
using F::operator();
};
} // namespace MyLib
现在,我们在自定义子类中装饰 TPredicate:
template <typename TPredicate, typename TRange>
struct Filtered_Range : boost::filtered_range<MyLib::Tagged<TPredicate>, TRange> {
using base_type = boost::filtered_range<MyLib::Tagged<TPredicate>, TRange>;
using base_type::base_type;
auto operator[](size_t i) const {
assert(i < this->size());
return *std::next(base_type::begin(), i);
}
using const_iterator = typename boost::range_iterator<base_type, void>::type;
};
并且我们扩展 is_filt_it
特性来检查 Tagged<>
谓词:
namespace detail {
template <typename T> struct is_tagged : std::false_type { };
template <typename F> struct is_tagged<MyLib::Tagged<F>> : std::true_type { };
template <typename T, typename = void> struct is_filt_it : std::false_type { };
template <typename F, typename... Args>
struct is_filt_it<boost::filter_iterator<F, Args...>,
std::enable_if_t<is_tagged<F>::value>> : std::true_type {
};
} // namespace detail
遗憾的是,这中断了:
Candidate template ignored: requirement 'detail::is_filt_it<boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<MyLib::Tagged<...>, bool>...
如您所见,Boost 已经 有 包装器(至少有时)并且它打破了我们的检测
尝试 #2(银河大脑)
那么我们是否会变得乏味并更改实际的迭代器类型?
没有! C++ 中有一个有时有点毒的特性:参数相关查找。 ADL 旨在引入“关联的命名空间”以供查找。事实证明,声明在模板参数(及其模板参数)中命名的类型的命名空间被认为是“关联的”。
所以:
namespace MyLib {
namespace AdlBarrier {
template <typename F> struct Tagged : F {
Tagged(F f) : F(std::move(f)) {}
using F::operator();
};
template <typename T> constexpr bool is_tagged(T&&) { return true; }
} // namespace AdlBarrier
using AdlBarrier::Tagged;
} // namespace MyLib
Filtered_Range
没有变化,并且:
namespace detail {
template <typename T, typename = void> struct is_filt_it : std::false_type { };
template <typename F, typename... Args>
struct is_filt_it<boost::filter_iterator<F, Args...>,
std::enable_if_t<is_tagged(static_cast<F*>(nullptr))>>
: std::true_type {
};
} // namespace detail
现在,您可以对自定义范围内的迭代器进行特殊处理:
{
auto evens = Filtered_Range([](auto n) { return (n % 2 == 0); }, nums);
auto it = evens.begin();
std::cout << "First Value = " << *(it) << "\n";
std::cout << "Second Value = " << *(it + 1) << "\n";
}
但是普通香草 boost::filtered_range
没有得到特殊待遇:
{
auto odds = boost::filtered_range([](auto n) { return (n % 2 == 1); }, nums);
auto it = odds.begin();
std::cout << "First Value = " << *(it) << "\n";
std::cout << "Second Value = " << *(it + 1) << "\n"; // doesn't compile
}
现场观看:https://godbolt.org/z/xhqjqa3Gc (or correctly not-compiling: https://godbolt.org/z/67vP6TEGc)