error: no match for ‘operator=’ (operand types are ‘const XXX’ and ‘std::remove_reference<const XXX&>::type’ {aka ‘const XXX’})
error: no match for ‘operator=’ (operand types are ‘const XXX’ and ‘std::remove_reference<const XXX&>::type’ {aka ‘const XXX’})
我尝试使用升压范围迭代器来实现 LINQ。当谈到与给定谓词的区别时,我遇到了一些问题。为了直接简单地描述我的问题,我写了一个最小的例子:
// test.cc
#include <algorithm>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>
#include <vector>
using namespace std;
template <typename R>
class Linq {
private:
R range_;
public:
typedef typename R::value_type value_type;
Linq(R& range) : range_(range) {}
Linq(const R& range) : range_(range) {}
~Linq() = default;
template <typename F>
auto Distinct(const F& f) {
auto ur = boost::range::unique(range_, f);
return Linq(ur);
}
auto Distinct() -> Linq<boost::range_detail::uniqued_range<R>> {
boost::range_detail::uniqued_range<R> ur =
range_ | boost::adaptors::uniqued;
return Linq<boost::range_detail::uniqued_range<R>>(ur);
}
template <typename F>
void for_each(const F& f) {
std::for_each(std::begin(range_), std::end(range_), f);
}
};
template <template <typename T> class linq_range_tmpl, typename R>
using linq_range_private =
linq_range_tmpl<decltype(std::begin(std::declval<R>()))>;
template <typename R>
using linq_range_iterator = linq_range_private<boost::iterator_range, R>;
// All the Linq object should be created by From function
template <typename R>
Linq<linq_range_iterator<R>> From(const R& range) {
linq_range_iterator<R> ir(range);
return Linq<decltype(ir)>(ir);
}
int main() {
std::vector<string> vec = {"Hello", "Hello", "Phoenix", "Jack", "Rose"};
auto filter = [](const string& str1, const string& str2) {
return str1.length() == str2.length();
};
auto Printer = [](const string& str) { cout << str << " "; };
From(vec).Distinct().for_each(Printer);
cout << endl;
//From(vec).Distinct(filter).for_each(Printer); // this statement will launch a compile error
cout << endl;
}
顺便说一句,我的运行环境如下:
- OS Ubuntu-20.04 LTS
- 编译器 gcc-9.3.0
- 增强版 1.71
如您所见,当我将语句 From(vec).Distinct(filter).for_each(Printer)
放入评论中时,一切正常。执行结果为:
$ Hello Phoenix Jack Rose
使用给定谓词的 distint 方法的结果应该如下所示
$ Hello Phoenix Jack
但是如果我不评论那条语句,我会收到很多错误信息:
$ g++ test.cc -std=c++17
In file included from /usr/include/c++/9/algorithm:62,
from test.cc:1:
/usr/include/c++/9/bits/stl_algo.h: In instantiation of ‘_ForwardIterator std::__unique(_ForwardIterator, _ForwardIterator, _BinaryPredicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _BinaryPredicate = __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(const string&, const string&)> >]’:
/usr/include/c++/9/bits/stl_algo.h:1036:27: required from ‘_FIter std::unique(_FIter, _FIter, _BinaryPredicate) [with _FIter = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _BinaryPredicate = main()::<lambda(const string&, const string&)>]’
/usr/include/boost/range/algorithm/unique.hpp:56:25: required from ‘typename boost::range_return<ForwardRange, re>::type boost::range::unique(ForwardRange&, BinaryPredicate) [with boost::range_return_value re = boost::return_begin_found; ForwardRange = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >; BinaryPredicate = main()::<lambda(const string&, const string&)>; typename boost::range_return<ForwardRange, re>::type = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
/usr/include/boost/range/algorithm/unique.hpp:92:54: required from ‘typename boost::range_return<SinglePassRange, boost::return_begin_found>::type boost::range::unique(ForwardRange&, BinaryPredicate) [with ForwardRange = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >; BinaryPredicate = main()::<lambda(const string&, const string&)>; typename boost::range_return<SinglePassRange, boost::return_begin_found>::type = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
test.cc:21:35: required from ‘auto Linq<R>::Distinct(const F&) [with F = main()::<lambda(const string&, const string&)>; R = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
test.cc:59:28: required from here
/usr/include/c++/9/bits/stl_algo.h:975:14: error: no match for ‘operator=’ (operand types are ‘const std::__cxx11::basic_string<char>’ and ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’})
975 | *++__dest = _GLIBCXX_MOVE(*__first);
| ^
In file included from /usr/include/c++/9/string:55,
from /usr/include/c++/9/stdexcept:39,
from /usr/include/c++/9/array:39,
from /usr/include/c++/9/tuple:39,
from /usr/include/c++/9/functional:54,
from /usr/include/c++/9/pstl/glue_algorithm_defs.h:13,
from /usr/include/c++/9/algorithm:71,
from test.cc:1:
/usr/include/c++/9/bits/basic_string.h:665:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ <near match>
665 | operator=(const basic_string& __str)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:665:7: note: passing ‘const std::__cxx11::basic_string<char>*’ as ‘this’ argument discards qualifiers
/usr/include/c++/9/bits/basic_string.h:732:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ <near match>
732 | operator=(basic_string&& __str)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:732:7: note: conversion of argument 1 would be ill-formed:
In file included from /usr/include/c++/9/algorithm:62,
from test.cc:1:
/usr/include/c++/9/bits/stl_algo.h:975:14: error: binding reference of type ‘std::__cxx11::basic_string<char>&&’ to ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’} discards qualifiers
975 | *++__dest = _GLIBCXX_MOVE(*__first);
| ^
In file included from /usr/include/c++/9/string:55,
from /usr/include/c++/9/stdexcept:39,
from /usr/include/c++/9/array:39,
from /usr/include/c++/9/tuple:39,
from /usr/include/c++/9/functional:54,
from /usr/include/c++/9/pstl/glue_algorithm_defs.h:13,
from /usr/include/c++/9/algorithm:71,
from test.cc:1:
/usr/include/c++/9/bits/basic_string.h:704:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
704 | operator=(const _CharT* __s)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:704:31: note: no known conversion for argument 1 from ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’} to ‘const char*’
704 | operator=(const _CharT* __s)
| ~~~~~~~~~~~~~~^~~
/usr/include/c++/9/bits/basic_string.h:715:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
715 | operator=(_CharT __c)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:715:24: note: no known conversion for argument 1 from ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’} to ‘char’
715 | operator=(_CharT __c)
| ~~~~~~~^~~
/usr/include/c++/9/bits/basic_string.h:795:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(std::initializer_list<_Tp>) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
795 | operator=(initializer_list<_CharT> __l)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:795:42: note: no known conversion for argument 1 from ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’} to ‘std::initializer_list<char>’
795 | operator=(initializer_list<_CharT> __l)
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~
/usr/include/c++/9/bits/basic_string.h:809:8: note: candidate: ‘template<class _Tp> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_If_sv<_Tp, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(const _Tp&) [with _Tp = _Tp; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
809 | operator=(const _Tp& __svt)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:809:8: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/9/bits/move.h:55,
from /usr/include/c++/9/bits/stl_pair.h:59,
from /usr/include/c++/9/utility:70,
from /usr/include/c++/9/algorithm:60,
from test.cc:1:
/usr/include/c++/9/type_traits: In substitution of ‘template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = std::integral_constant<bool, false>::value; _Tp = std::__cxx11::basic_string<char>&]’:
/usr/include/c++/9/bits/basic_string.h:117:8: required by substitution of ‘template<class _CharT, class _Traits, class _Alloc> template<class _Tp, class _Res> using _If_sv = std::enable_if_t<std::__and_<std::is_convertible<const _Tp&, std::basic_string_view<_CharT, _Traits> >, std::__not_<std::is_convertible<const _Tp*, const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>*> >, std::__not_<std::is_convertible<const _Tp&, const _CharT*> > >::value, _Res> [with _Tp = std::__cxx11::basic_string<char>; _Res = std::__cxx11::basic_string<char>&; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
/usr/include/c++/9/bits/basic_string.h:809:8: required by substitution of ‘template<class _Tp> std::__cxx11::basic_string<char>::_If_sv<_Tp, std::__cxx11::basic_string<char>&> std::__cxx11::basic_string<char>::operator=<_Tp>(const _Tp&) [with _Tp = std::__cxx11::basic_string<char>]’
/usr/include/c++/9/bits/stl_algo.h:975:14: required from ‘_ForwardIterator std::__unique(_ForwardIterator, _ForwardIterator, _BinaryPredicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _BinaryPredicate = __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(const string&, const string&)> >]’
/usr/include/c++/9/bits/stl_algo.h:1036:27: required from ‘_FIter std::unique(_FIter, _FIter, _BinaryPredicate) [with _FIter = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _BinaryPredicate = main()::<lambda(const string&, const string&)>]’
/usr/include/boost/range/algorithm/unique.hpp:56:25: required from ‘typename boost::range_return<ForwardRange, re>::type boost::range::unique(ForwardRange&, BinaryPredicate) [with boost::range_return_value re = boost::return_begin_found; ForwardRange = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >; BinaryPredicate = main()::<lambda(const string&, const string&)>; typename boost::range_return<ForwardRange, re>::type = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
/usr/include/boost/range/algorithm/unique.hpp:92:54: required from ‘typename boost::range_return<SinglePassRange, boost::return_begin_found>::type boost::range::unique(ForwardRange&, BinaryPredicate) [with ForwardRange = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >; BinaryPredicate = main()::<lambda(const string&, const string&)>; typename boost::range_return<SinglePassRange, boost::return_begin_found>::type = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
test.cc:21:35: required from ‘auto Linq<R>::Distinct(const F&) [with F = main()::<lambda(const string&, const string&)>; R = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
test.cc:59:28: required from here
/usr/include/c++/9/type_traits:2385:11: error: no type named ‘type’ in ‘struct std::enable_if<false, std::__cxx11::basic_string<char>&>’
2385 | using enable_if_t = typename enable_if<_Cond, _Tp>::type;
我被这个问题困扰了好几天。我尽我所能来解决这个问题,但它仍然不起作用。我已经用尽了我的技巧。谁能给我一些提示来解决它?
auto ur = boost::range::unique(range_, f);
尝试就地修改 range_
但其元素是只读的 (const
)。适配器 uniqued
不会那样做。可能是你不小心把它们弄混了。从事物的名称来看,这似乎是一个更好的匹配:
template <typename F>
auto Distinct(F const& f) {
auto ur = range_
| boost::adaptors::filtered(f)
| boost::adaptors::uniqued;
return Linq<decltype(ur)>(ur);
}
现在,'filter' 是用词不当,因为它需要谓词。你的意思可能是comparator
?然而:
- boost::adaptors::unqied does not support custom equality comparators
- 只有当范围由同一个比较器排序时,使用自定义比较器才有意义
总而言之,您似乎只为现有 Range 库获取一些语法糖就做了太多工作。
另请参阅 Is there a LINQ library for C++? 了解有关此想法的一些设计想法。
我尝试使用升压范围迭代器来实现 LINQ。当谈到与给定谓词的区别时,我遇到了一些问题。为了直接简单地描述我的问题,我写了一个最小的例子:
// test.cc
#include <algorithm>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>
#include <vector>
using namespace std;
template <typename R>
class Linq {
private:
R range_;
public:
typedef typename R::value_type value_type;
Linq(R& range) : range_(range) {}
Linq(const R& range) : range_(range) {}
~Linq() = default;
template <typename F>
auto Distinct(const F& f) {
auto ur = boost::range::unique(range_, f);
return Linq(ur);
}
auto Distinct() -> Linq<boost::range_detail::uniqued_range<R>> {
boost::range_detail::uniqued_range<R> ur =
range_ | boost::adaptors::uniqued;
return Linq<boost::range_detail::uniqued_range<R>>(ur);
}
template <typename F>
void for_each(const F& f) {
std::for_each(std::begin(range_), std::end(range_), f);
}
};
template <template <typename T> class linq_range_tmpl, typename R>
using linq_range_private =
linq_range_tmpl<decltype(std::begin(std::declval<R>()))>;
template <typename R>
using linq_range_iterator = linq_range_private<boost::iterator_range, R>;
// All the Linq object should be created by From function
template <typename R>
Linq<linq_range_iterator<R>> From(const R& range) {
linq_range_iterator<R> ir(range);
return Linq<decltype(ir)>(ir);
}
int main() {
std::vector<string> vec = {"Hello", "Hello", "Phoenix", "Jack", "Rose"};
auto filter = [](const string& str1, const string& str2) {
return str1.length() == str2.length();
};
auto Printer = [](const string& str) { cout << str << " "; };
From(vec).Distinct().for_each(Printer);
cout << endl;
//From(vec).Distinct(filter).for_each(Printer); // this statement will launch a compile error
cout << endl;
}
顺便说一句,我的运行环境如下:
- OS Ubuntu-20.04 LTS
- 编译器 gcc-9.3.0
- 增强版 1.71
如您所见,当我将语句 From(vec).Distinct(filter).for_each(Printer)
放入评论中时,一切正常。执行结果为:
$ Hello Phoenix Jack Rose
使用给定谓词的 distint 方法的结果应该如下所示
$ Hello Phoenix Jack
但是如果我不评论那条语句,我会收到很多错误信息:
$ g++ test.cc -std=c++17
In file included from /usr/include/c++/9/algorithm:62,
from test.cc:1:
/usr/include/c++/9/bits/stl_algo.h: In instantiation of ‘_ForwardIterator std::__unique(_ForwardIterator, _ForwardIterator, _BinaryPredicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _BinaryPredicate = __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(const string&, const string&)> >]’:
/usr/include/c++/9/bits/stl_algo.h:1036:27: required from ‘_FIter std::unique(_FIter, _FIter, _BinaryPredicate) [with _FIter = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _BinaryPredicate = main()::<lambda(const string&, const string&)>]’
/usr/include/boost/range/algorithm/unique.hpp:56:25: required from ‘typename boost::range_return<ForwardRange, re>::type boost::range::unique(ForwardRange&, BinaryPredicate) [with boost::range_return_value re = boost::return_begin_found; ForwardRange = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >; BinaryPredicate = main()::<lambda(const string&, const string&)>; typename boost::range_return<ForwardRange, re>::type = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
/usr/include/boost/range/algorithm/unique.hpp:92:54: required from ‘typename boost::range_return<SinglePassRange, boost::return_begin_found>::type boost::range::unique(ForwardRange&, BinaryPredicate) [with ForwardRange = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >; BinaryPredicate = main()::<lambda(const string&, const string&)>; typename boost::range_return<SinglePassRange, boost::return_begin_found>::type = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
test.cc:21:35: required from ‘auto Linq<R>::Distinct(const F&) [with F = main()::<lambda(const string&, const string&)>; R = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
test.cc:59:28: required from here
/usr/include/c++/9/bits/stl_algo.h:975:14: error: no match for ‘operator=’ (operand types are ‘const std::__cxx11::basic_string<char>’ and ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’})
975 | *++__dest = _GLIBCXX_MOVE(*__first);
| ^
In file included from /usr/include/c++/9/string:55,
from /usr/include/c++/9/stdexcept:39,
from /usr/include/c++/9/array:39,
from /usr/include/c++/9/tuple:39,
from /usr/include/c++/9/functional:54,
from /usr/include/c++/9/pstl/glue_algorithm_defs.h:13,
from /usr/include/c++/9/algorithm:71,
from test.cc:1:
/usr/include/c++/9/bits/basic_string.h:665:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ <near match>
665 | operator=(const basic_string& __str)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:665:7: note: passing ‘const std::__cxx11::basic_string<char>*’ as ‘this’ argument discards qualifiers
/usr/include/c++/9/bits/basic_string.h:732:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ <near match>
732 | operator=(basic_string&& __str)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:732:7: note: conversion of argument 1 would be ill-formed:
In file included from /usr/include/c++/9/algorithm:62,
from test.cc:1:
/usr/include/c++/9/bits/stl_algo.h:975:14: error: binding reference of type ‘std::__cxx11::basic_string<char>&&’ to ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’} discards qualifiers
975 | *++__dest = _GLIBCXX_MOVE(*__first);
| ^
In file included from /usr/include/c++/9/string:55,
from /usr/include/c++/9/stdexcept:39,
from /usr/include/c++/9/array:39,
from /usr/include/c++/9/tuple:39,
from /usr/include/c++/9/functional:54,
from /usr/include/c++/9/pstl/glue_algorithm_defs.h:13,
from /usr/include/c++/9/algorithm:71,
from test.cc:1:
/usr/include/c++/9/bits/basic_string.h:704:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
704 | operator=(const _CharT* __s)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:704:31: note: no known conversion for argument 1 from ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’} to ‘const char*’
704 | operator=(const _CharT* __s)
| ~~~~~~~~~~~~~~^~~
/usr/include/c++/9/bits/basic_string.h:715:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
715 | operator=(_CharT __c)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:715:24: note: no known conversion for argument 1 from ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’} to ‘char’
715 | operator=(_CharT __c)
| ~~~~~~~^~~
/usr/include/c++/9/bits/basic_string.h:795:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(std::initializer_list<_Tp>) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
795 | operator=(initializer_list<_CharT> __l)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:795:42: note: no known conversion for argument 1 from ‘std::remove_reference<const std::__cxx11::basic_string<char>&>::type’ {aka ‘const std::__cxx11::basic_string<char>’} to ‘std::initializer_list<char>’
795 | operator=(initializer_list<_CharT> __l)
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~
/usr/include/c++/9/bits/basic_string.h:809:8: note: candidate: ‘template<class _Tp> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_If_sv<_Tp, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(const _Tp&) [with _Tp = _Tp; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
809 | operator=(const _Tp& __svt)
| ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:809:8: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/9/bits/move.h:55,
from /usr/include/c++/9/bits/stl_pair.h:59,
from /usr/include/c++/9/utility:70,
from /usr/include/c++/9/algorithm:60,
from test.cc:1:
/usr/include/c++/9/type_traits: In substitution of ‘template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = std::integral_constant<bool, false>::value; _Tp = std::__cxx11::basic_string<char>&]’:
/usr/include/c++/9/bits/basic_string.h:117:8: required by substitution of ‘template<class _CharT, class _Traits, class _Alloc> template<class _Tp, class _Res> using _If_sv = std::enable_if_t<std::__and_<std::is_convertible<const _Tp&, std::basic_string_view<_CharT, _Traits> >, std::__not_<std::is_convertible<const _Tp*, const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>*> >, std::__not_<std::is_convertible<const _Tp&, const _CharT*> > >::value, _Res> [with _Tp = std::__cxx11::basic_string<char>; _Res = std::__cxx11::basic_string<char>&; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
/usr/include/c++/9/bits/basic_string.h:809:8: required by substitution of ‘template<class _Tp> std::__cxx11::basic_string<char>::_If_sv<_Tp, std::__cxx11::basic_string<char>&> std::__cxx11::basic_string<char>::operator=<_Tp>(const _Tp&) [with _Tp = std::__cxx11::basic_string<char>]’
/usr/include/c++/9/bits/stl_algo.h:975:14: required from ‘_ForwardIterator std::__unique(_ForwardIterator, _ForwardIterator, _BinaryPredicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _BinaryPredicate = __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(const string&, const string&)> >]’
/usr/include/c++/9/bits/stl_algo.h:1036:27: required from ‘_FIter std::unique(_FIter, _FIter, _BinaryPredicate) [with _FIter = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _BinaryPredicate = main()::<lambda(const string&, const string&)>]’
/usr/include/boost/range/algorithm/unique.hpp:56:25: required from ‘typename boost::range_return<ForwardRange, re>::type boost::range::unique(ForwardRange&, BinaryPredicate) [with boost::range_return_value re = boost::return_begin_found; ForwardRange = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >; BinaryPredicate = main()::<lambda(const string&, const string&)>; typename boost::range_return<ForwardRange, re>::type = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
/usr/include/boost/range/algorithm/unique.hpp:92:54: required from ‘typename boost::range_return<SinglePassRange, boost::return_begin_found>::type boost::range::unique(ForwardRange&, BinaryPredicate) [with ForwardRange = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >; BinaryPredicate = main()::<lambda(const string&, const string&)>; typename boost::range_return<SinglePassRange, boost::return_begin_found>::type = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
test.cc:21:35: required from ‘auto Linq<R>::Distinct(const F&) [with F = main()::<lambda(const string&, const string&)>; R = boost::iterator_range<__gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >]’
test.cc:59:28: required from here
/usr/include/c++/9/type_traits:2385:11: error: no type named ‘type’ in ‘struct std::enable_if<false, std::__cxx11::basic_string<char>&>’
2385 | using enable_if_t = typename enable_if<_Cond, _Tp>::type;
我被这个问题困扰了好几天。我尽我所能来解决这个问题,但它仍然不起作用。我已经用尽了我的技巧。谁能给我一些提示来解决它?
auto ur = boost::range::unique(range_, f);
尝试就地修改 range_
但其元素是只读的 (const
)。适配器 uniqued
不会那样做。可能是你不小心把它们弄混了。从事物的名称来看,这似乎是一个更好的匹配:
template <typename F>
auto Distinct(F const& f) {
auto ur = range_
| boost::adaptors::filtered(f)
| boost::adaptors::uniqued;
return Linq<decltype(ur)>(ur);
}
现在,'filter' 是用词不当,因为它需要谓词。你的意思可能是comparator
?然而:
- boost::adaptors::unqied does not support custom equality comparators
- 只有当范围由同一个比较器排序时,使用自定义比较器才有意义
总而言之,您似乎只为现有 Range 库获取一些语法糖就做了太多工作。
另请参阅 Is there a LINQ library for C++? 了解有关此想法的一些设计想法。