How to inherit from boost :: asio :: streambuf after version 1.70.0? - c++

After upgrade boost version 1.72.0, the following program which uses boost::asio cannot be compiled.I noticed that the read_until signature has changed since version 1.70.0.
Example in Coliru
#include <iostream>
#include <boost/asio.hpp>
class framed_streambuf: public boost::asio::streambuf
{
};
int main()
{
std::cout << "Using Boost "
<< BOOST_VERSION / 100000 << "." // major version
<< BOOST_VERSION / 100 % 1000 << "." // minor version
<< BOOST_VERSION % 100 // patch level
<< std::endl;
using boost::asio::ip::tcp;
framed_streambuf streambuf;
boost::asio::io_service io_service{1};
tcp::socket client_socket(io_service);
auto bytes_transferred = read_until(client_socket, streambuf, '#');
return 0;
}
Compilation errors:
/usr/local/include/boost/asio/impl/read_until.hpp: In instantiation of 'std::size_t boost::asio::read_until(SyncReadStream&, DynamicBuffer_v1&&, char, boost::system::error_code&, typename std::enable_if<(boost::asio::is_dynamic_buffer_v1<typename std::decay<_Func>::type>::value && (! boost::asio::is_dynamic_buffer_v2<typename std::decay<_Func>::type>::value))>::type*) [with SyncReadStream = boost::asio::basic_stream_socket<boost::asio::ip::tcp>; DynamicBuffer_v1 = framed_streambuf&; std::size_t = long unsigned int; typename std::enable_if<(boost::asio::is_dynamic_buffer_v1<typename std::decay<_Func>::type>::value && (! boost::asio::is_dynamic_buffer_v2<typename std::decay<_Func>::type>::value))>::type = void]':
/usr/local/include/boost/asio/impl/read_until.hpp:86:45: required from 'std::size_t boost::asio::read_until(SyncReadStream&, DynamicBuffer_v1&&, char, typename std::enable_if<(boost::asio::is_dynamic_buffer_v1<typename std::decay<_Func>::type>::value && (! boost::asio::is_dynamic_buffer_v2<typename std::decay<_Func>::type>::value))>::type*) [with SyncReadStream = boost::asio::basic_stream_socket<boost::asio::ip::tcp>; DynamicBuffer_v1 = framed_streambuf&; std::size_t = long unsigned int; typename std::enable_if<(boost::asio::is_dynamic_buffer_v1<typename std::decay<_Func>::type>::value && (! boost::asio::is_dynamic_buffer_v2<typename std::decay<_Func>::type>::value))>::type = void]'
main.cpp:20:70: required from here
/usr/local/include/boost/asio/impl/read_until.hpp:101:42: error: use of deleted function 'framed_streambuf::framed_streambuf(const framed_streambuf&)'
101 | typename decay<DynamicBuffer_v1>::type b(
| ^
main.cpp:4:7: note: 'framed_streambuf::framed_streambuf(const framed_streambuf&)' is implicitly deleted because the default definition would be ill-formed:
4 | class framed_streambuf: public boost::asio::streambuf
| ^~~~~~~~~~~~~~~~
main.cpp:4:7: error: use of deleted function 'boost::asio::basic_streambuf<>::basic_streambuf(const boost::asio::basic_streambuf<>&)'
In file included from /usr/local/include/boost/asio.hpp:36,
from main.cpp:2:
/usr/local/include/boost/asio/basic_streambuf.hpp:111:7: note: 'boost::asio::basic_streambuf<>::basic_streambuf(const boost::asio::basic_streambuf<>&)' is implicitly deleted because the default definition would be ill-formed:
111 | class basic_streambuf
| ^~~~~~~~~~~~~~~
/usr/local/include/boost/asio/basic_streambuf.hpp:111:7: error: 'boost::asio::detail::noncopyable::noncopyable(const boost::asio::detail::noncopyable&)' is private within this context
In file included from /usr/local/include/boost/asio/detail/std_fenced_block.hpp:23,
from /usr/local/include/boost/asio/detail/fenced_block.hpp:24,
from /usr/local/include/boost/asio/detail/executor_op.hpp:19,
from /usr/local/include/boost/asio/impl/system_executor.hpp:18,
from /usr/local/include/boost/asio/system_executor.hpp:129,
from /usr/local/include/boost/asio/associated_executor.hpp:21,
from /usr/local/include/boost/asio.hpp:21,
from main.cpp:2:
/usr/local/include/boost/asio/detail/noncopyable.hpp:32:3: note: declared private here
32 | noncopyable(const noncopyable&);
| ^~~~~~~~~~~
In file included from /usr/local/include/boost/asio/read_until.hpp:2795,
from /usr/local/include/boost/asio.hpp:114,
from main.cpp:2:
/usr/local/include/boost/asio/impl/read_until.hpp:108:59: error: 'framed_streambuf&' is not a class, struct, or union type
108 | typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
| ^~~~~~~~~~~~
/usr/local/include/boost/asio/impl/read_until.hpp:109:44: error: 'framed_streambuf&' is not a class, struct, or union type
109 | typedef buffers_iterator<buffers_type> iterator;
Since boost 1.70.0, the signature of read_until has changed:
template <typename SyncReadStream, typename DynamicBuffer_v1>
std::size_t read_until(SyncReadStream& s,
BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
char delim, boost::system::error_code& ec,
typename enable_if<
is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
&& !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
I know very little about enable_if, does it matter here?

Related

C++20 concept that supposedly depends on itself

In my world, a StrictNodeType should be anything that defines the types PredContainer and SuccContainer, so I wrote
template<typename N>
concept StrictNodeType = requires {
typename N::PredContainer;
typename N::SuccContainer;
};
However, GCC-11.2 gives me the following error:
error: satisfaction of atomic constraint 'requires{typename N::PredContainer;typename N::SuccContainer;} [with N = typename std::remove_cvref<_Tp>::type::Node]' depends on itself
164 | concept StrictNodeType = requires {
| ^~~~~~~~~~
165 | typename N::PredContainer;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
166 | typename N::SuccContainer;something;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167 | };
How is that possible? Why can't GCC simply inspect the given type and check if it provides the requested subtypes?
Here's a minimum breaking example:
#include <type_traits>
template<typename N>
concept StrictNodeType = requires {
typename N::something;
};
template<StrictNodeType N> using Int = int;
template<int>
struct X {using type = Int<X>; };
using ThisBreaks = Int<X<0>>;
It seems there is an infinite recursion issue that constrains a concept more than it would be without it. I made a few changes to get more directly at the issue:
#include <type_traits>
template<typename N>
concept StrictNodeType = requires {
typename N::something;
};
#if 1
template<StrictNodeType N> using Int = int;
#else
template<typename N> using Int = int;
#endif
template<int>
struct X { using something = Int<X<0>>; };
using ThisBreaks=Int<X<0>>;
ThisBreaks foo()
{
return ThisBreaks{};
}
This yields the following error:
<source>:15:37: error: template constraint failure for 'template<class N> requires StrictNodeType<N> using Int = int'
15 | struct X { using something = Int<X<0>>; };
| ^~
<source>:15:37: note: constraints not satisfied
<source>: In substitution of 'template<class N> requires StrictNodeType<N> using Int = int [with N = X<0>]':
<source>:15:37: required from here
<source>:4:9: required for the satisfaction of 'StrictNodeType<N>' [with N = X<0>]
<source>:4:26: in requirements [with N = X<0>]
<source>:5:14: note: the required type 'typename N::something' is invalid
5 | typename N::something;
| ~~~~~~~~~^~~~~~~~~~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
<source>:17:25: error: template constraint failure for 'template<class N> requires StrictNodeType<N> using Int = int'
17 | using ThisBreaks=Int<X<0>>;
| ^~
<source>:17:25: note: constraints not satisfied
<source>: In substitution of 'template<class N> requires StrictNodeType<N> using Int = int [with N = X<0>]':
<source>:17:25: required from here
<source>:4:9: required for the satisfaction of 'StrictNodeType<N>' [with N = X<0>]
<source>:4:26: in requirements [with N = X<0>]
<source>:5:14: note: the required type 'typename N::something' is invalid
5 | typename N::something;
| ~~~~~~~~~^~~~~~~~~~~~~
<source>:19:1: error: 'ThisBreaks' does not name a type
19 | ThisBreaks foo()
| ^~~~~~~~~~
Compiler returned: 1
Changing #if 1 to #if 0 compiles fine, only the Concept objects to the infinite recursion.
(Play with it here: https://godbolt.org/z/56Yd7W3sf )

C++ concept to enforce field of particular type [duplicate]

Consider the following code (Godbolt):
#include <iostream>
//#include <concepts>
#include <type_traits>
// Since the latest clang doesn't have <concepts>,
// took this here: https://en.cppreference.com/w/cpp/concepts/same_as
// Using of std::same_as still gives an error in GCC.
namespace detail {
template< class T, class U >
concept SameHelper = std::is_same_v<T, U>;
}
template< class T, class U >
concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;
template<typename T>
concept HasStr = requires(T a) { { a.str } -> same_as<const char*>; };
struct A {
const char* str = "A";
};
const char* f(HasStr auto has_str) {
return has_str.str;
}
int main() {
A a;
std::cout << f(a) << "\n";
return 0;
}
Clang 10.0.1 successfully compiles this program. But GCC 10.2 fails:
<source>: In function 'int main()':
<source>:28:21: error: use of function 'const char* f(auto:11) [with auto:11 = A]' with unsatisfied constraints
28 | std::cout << f(a) << "\n";
| ^
<source>:22:13: note: declared here
22 | const char* f(HasStr auto has_str) {
| ^
<source>:22:13: note: constraints not satisfied
<source>: In instantiation of 'const char* f(auto:11) [with auto:11 = A]':
<source>:28:21: required from here
<source>:16:9: required for the satisfaction of 'HasStr<auto:11>' [with auto:11 = A]
<source>:16:18: in requirements with 'T a' [with T = A]
<source>:16:38: note: 'a.str' does not satisfy return-type-requirement, because
16 | concept HasStr = requires(T a) { { a.str } -> same_as<const char*>; };
| ~~^~~
<source>:16:36: error: deduced expression type does not satisfy placeholder constraints
16 | concept HasStr = requires(T a) { { a.str } -> same_as<const char*>; };
| ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:16:36: note: constraints not satisfied
<source>:9:13: required for the satisfaction of 'SameHelper<T, U>' [with T = const char*&; U = const char*]
<source>:13:9: required for the satisfaction of 'same_as<const char*&, const char*>'
<source>:9:31: note: the expression 'is_same_v<T, U> [with T = const char*&; U = const char*]' evaluated to 'false'
9 | concept SameHelper = std::is_same_v<T, U>;
| ~~~~~^~~~~~~~~~~~~~~
Compiler returned: 1
The most interesting part is:
<source>:9:31: note: the expression 'is_same_v<T, U> [with T = const char*&; U = const char*]' evaluated to 'false'
As I understand it, in the compound requirement { a.str } expression has type const char*& instead of const char*. So, why is this happening? Which compiler is correct?
By my reading of [expr.prim.req.compound]/1, GCC is correct to emit an error:
The immediately-declared constraint ([temp.param]) of the type-constraint for decltype((E)) shall be satisfied.
With an accompanying example:
requires {
{ E1 } -> C;
{ E2 } -> D<A₁, ⋯, An>;
};
is equivalent to
requires {
E1; requires C<decltype((E1))>;
E2; requires D<decltype((E2)), A₁, ⋯, An>;
};
decltype((a.str)) is indeed const char*&, so I would expect that this is what's passed to same_as.

compile error when trying to use pointer-to-member function as projection to ranges::find()

I want to search an input range for an element that has a certain value in a member via an accessor.
range-v3 documentation is... thin, but there are sources such as this answer by AFAIK the 2 main range-v3 developers indicates this kind of thing should Just Work, albeit with sort not find.
Given the code, compiled with g++ -std=c++17 against ericniebler/range-v3 release range-v3-0.10.0, using g++.exe (Rev2, Built by MSYS2 project) 9.3.0:
#include <range/v3/algorithm/find.hpp>
#include <vector>
auto
main() -> int
{
struct S {
int i{};
auto get_i() const { return i; }
};
auto const ss = std::vector<S>(10);
ranges::find(ss, 1, &S::get_i);
return 0;
}
I get a spew of errors:
test.cpp: In function 'int main()':
test.cpp:14:31: error: no match for call to '(const ranges::find_fn) (const std::vector<main()::S>&, int, int (main()::S::*)() const)'
14 | ranges::find(ss, 1, &S::get_i);
| ^
In file included from FOO/include/range-v3/range/v3/range_fwd.hpp:24,
from FOO/include/range-v3/range/v3/algorithm/find.hpp:18,
from test.cpp:1:
FOO/include/range-v3/range/v3/detail/config.hpp:618:27: note: candidate: 'template<class I, class S, class V, class P> constexpr concepts::return_t<I, typename std::enable_if<(((input_iterator<I> && sentinel_for<S, I>) && indirect_relation<ranges::equal_to, typename ranges::detail::select_projected_<P>::apply<I>, const V*>) && concepts::detail::CPP_true(concepts::detail::Nil{})), void>::type> ranges::find_fn::operator()(I, S, const V&, P) const'
618 | #define RANGES_FUNC(NAME) operator() RANGES_FUNC_CONST_ /**/
| ^~~~~~~~
FOO/include/range-v3/range/v3/algorithm/find.hpp:47:24: note: in expansion of macro 'RANGES_FUNC'
47 | constexpr auto RANGES_FUNC(find)(I first, S last, V const & val, P proj = P{})
| ^~~~~~~~~~~
FOO/include/range-v3/range/v3/detail/config.hpp:618:27: note: template argument deduction/substitution failed:
618 | #define RANGES_FUNC(NAME) operator() RANGES_FUNC_CONST_ /**/
| ^~~~~~~~
FOO/include/range-v3/range/v3/algorithm/find.hpp:47:24: note: in expansion of macro 'RANGES_FUNC'
47 | constexpr auto RANGES_FUNC(find)(I first, S last, V const & val, P proj = P{})
| ^~~~~~~~~~~
In file included from FOO/include/range-v3/range/v3/iterator/access.hpp:22,
from FOO/include/range-v3/range/v3/iterator/concepts.hpp:30,
from FOO/include/range-v3/range/v3/algorithm/find.hpp:22,
from test.cpp:1:
FOO/include/range-v3/std/detail/associated_types.hpp: In substitution of 'template<bool B, class T> using enable_if_t = typename ranges::detail::enable_if::apply<T> [with bool B = ranges::readable<std::vector<main()::S> >; T = std::vector<main()::S>]':
FOO/include/range-v3/range/v3/iterator/concepts.hpp:561:19: required by substitution of 'template<class I> using apply = ranges::detail::enable_if_t<(bool)(readable<I>), I> [with I = std::vector<main()::S>]'
FOO/include/range-v3/range/v3/algorithm/find.hpp:48:15: required by substitution of 'template<class I, class S, class V, class P> constexpr concepts::return_t<I, typename std::enable_if<(((input_iterator<I> && sentinel_for<S, I>) && indirect_relation<ranges::equal_to, typename ranges::detail::select_projected_<P>::apply<I>, const V*>) && concepts::detail::CPP_true(concepts::detail::Nil{})), void>::type> ranges::find_fn::operator()(I, S, const V&, P) const [with I = std::vector<main()::S>; S = int; V = int (main()::S::*)() const; P = ranges::identity]'
test.cpp:14:31: required from here
FOO/include/range-v3/std/detail/associated_types.hpp:73:15: error: no class template named 'apply' in 'struct ranges::detail::enable_if<false>'
73 | using enable_if_t = typename enable_if<B>::template apply<T>;
| ^~~~~~~~~~~
In file included from FOO/include/range-v3/range/v3/range_fwd.hpp:24,
from FOO/include/range-v3/range/v3/algorithm/find.hpp:18,
from test.cpp:1:
FOO/include/range-v3/range/v3/detail/config.hpp:618:27: note: candidate: 'template<class Rng, class V, class P> constexpr concepts::return_t<typename ranges::detail::if_then<forwarding_range_<R> >::apply<decltype (ranges::_::begin(declval<Rng&>())), ranges::dangling>, typename std::enable_if<((input_range<Rng> && indirect_relation<ranges::equal_to, typename ranges::detail::select_projected_<P1>::apply<decltype (ranges::_::begin(declval<Rng&>()))>, const V*>) && concepts::detail::CPP_true(concepts::detail::Nil{})), void>::type> ranges::find_fn::operator()(Rng&&, const V&, P) const'
618 | #define RANGES_FUNC(NAME) operator() RANGES_FUNC_CONST_ /**/
| ^~~~~~~~
FOO/include/range-v3/range/v3/algorithm/find.hpp:60:24: note: in expansion of macro 'RANGES_FUNC'
60 | constexpr auto RANGES_FUNC(find)(Rng && rng, V const & val, P proj = P{})
| ^~~~~~~~~~~
FOO/include/range-v3/range/v3/detail/config.hpp:618:27: note: template argument deduction/substitution failed:
618 | #define RANGES_FUNC(NAME) operator() RANGES_FUNC_CONST_ /**/
| ^~~~~~~~
FOO/include/range-v3/range/v3/algorithm/find.hpp:60:24: note: in expansion of macro 'RANGES_FUNC'
60 | constexpr auto RANGES_FUNC(find)(Rng && rng, V const & val, P proj = P{})
| ^~~~~~~~~~~
In file included from FOO/include/range-v3/range/v3/iterator/access.hpp:22,
from FOO/include/range-v3/range/v3/iterator/concepts.hpp:30,
from FOO/include/range-v3/range/v3/algorithm/find.hpp:22,
from test.cpp:1:
FOO/include/range-v3/std/detail/associated_types.hpp: In substitution of 'template<bool B, class T> using enable_if_t = typename ranges::detail::enable_if::apply<T> [with bool B = ranges::indirectly_regular_unary_invocable<int (main()::S::*)() const, __gnu_cxx::__normal_iterator<const main()::S*, std::vector<main()::S> > >; T = ranges::detail::projected_<__gnu_cxx::__normal_iterator<const main()::S*, std::vector<main()::S> >, int (main()::S::*)() const>]':
FOO/include/range-v3/range/v3/iterator/concepts.hpp:552:19: required by substitution of 'template<class Proj> template<class I> using apply = ranges::detail::enable_if_t<(bool)(indirectly_regular_unary_invocable<Proj, I>), ranges::detail::projected_<I, Proj> > [with I = __gnu_cxx::__normal_iterator<const main()::S*, std::vector<main()::S> >; Proj = int (main()::S::*)() const]'
FOO/include/range-v3/range/v3/algorithm/find.hpp:61:15: required by substitution of 'template<class Rng, class V, class P> constexpr concepts::return_t<typename ranges::detail::if_then<forwarding_range_<R> >::apply<decltype (ranges::_::begin(declval<Rng&>())), ranges::dangling>, typename std::enable_if<((input_range<Rng> && indirect_relation<ranges::equal_to, typename ranges::detail::select_projected_<P1>::apply<decltype (ranges::_::begin(declval<Rng&>()))>, const V*>) && concepts::detail::CPP_true(concepts::detail::Nil{})), void>::type> ranges::find_fn::operator()(Rng&&, const V&, P) const [with Rng = const std::vector<main()::S>&; V = int; P = int (main()::S::*)() const]'
test.cpp:14:31: required from here
FOO/include/range-v3/std/detail/associated_types.hpp:73:15: error: no class template named 'apply' in 'struct ranges::detail::enable_if<false>'
73 | using enable_if_t = typename enable_if<B>::template apply<T>;
| ^~~~~~~~~~~
shell returned 1
Making the projection a lambda...
ranges::find( ss, 1, [](auto const& s){ return s.get_i(); } );
...works but seems wasted typing.
Referring directly to the data member...
ranges::find(ss, 1, &S::i);
...works but is not possible if it should be encapsulated behind a const getter, transformer, etc.
What am I doing wrong? Can I not use a pointer-to-member-function as projection? Is it intended?
Edit: clang++ (also on MSYS2) does work here. So I guess this must be a bug in g++. Off to Bugzilla I go... edit: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94973
This is caused by GCC on Windows defaulting to -fms-extensions for compatibility with Microsoft compilers, and that pulling in a non-standard extension that introduces ambiguity between pointers-to-member-data vs -functions written as instance.*member.
We can pass -fno-ms-extensions to stop this and compile such code succesfully, until GCC remove that particular extension, which seems unnecessary and unhelpful nowadays.
Jonathan answered this on my GCC bug 94973:
Jonathan Wakely 2020-05-06 16:26:58 UTC
Aha, the same problem happens on linux if I compile with -fms-extensions
This is the old MS extension that causes x.*f to be accepted when f is a pointer to member function, which should only be valid when used as (x.*f)().
That causes ranges::invoke to think that the projection is a pointer to data member, when actually it's a pointer to member function.
See also PR 94771 comment 4.
Jason, do we want to disable that extension in SFINAE contexts?
Jonathan Wakely 2020-05-06 16:47:42 UTC
They're on by default for mingw, for compatibility with the MS compiler (but in this case it seems the relevant extension is ancient history).

g++: range-based for loop not compile without using namespace std;

The following code
#include <iostream>
#include <string>
using namespace std;
template <typename A> std::string to_string(const A& v) {
bool first = true;
std::string res = "{";
for (const auto &x : v) {
if (!first) {
res += ", ";
}
first = false;
res += to_string(x);
}
res += "}";
return res;
}
void debug_out() { std::cerr << std::endl; }
template <typename Head, typename... Tail> void debug_out(const Head& H, const Tail&... T) {
std::cerr << " " << to_string(H);
debug_out(T...);
}
#define debug(...) std::cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
int main() {
int x = 3;
debug(x);
return 0;
}
complies with GCC 9.3.0 and outputs [x]: 3 when run. However, if the 3rd line using namespace std; is commented out, the code does not compile and the errors are
prog.cc: In instantiation of 'std::string to_string(const A&) [with A = int; std::string = std::__cxx11::basic_string<char>]':
prog.cc:21:32: required from 'void debug_out(const Head&, const Tail& ...) [with Head = int; Tail = {}]'
prog.cc:32:3: required from here
prog.cc:7:3: error: 'begin' was not declared in this scope; did you mean 'std::begin'?
7 | for (const auto &x : v) {
| ^~~
| std::begin
In file included from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/string:54,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/locale_classes.h:40,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/ios_base.h:41,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ios:42,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ostream:38,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/iostream:39,
from prog.cc:1:
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/range_access.h:105:37: note: 'std::begin' declared here
105 | template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
| ^~~~~
prog.cc:7:3: error: 'end' was not declared in this scope; did you mean 'std::end'?
7 | for (const auto &x : v) {
| ^~~
| std::end
In file included from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/string:54,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/locale_classes.h:40,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/ios_base.h:41,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ios:42,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ostream:38,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/iostream:39,
from prog.cc:1:
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/range_access.h:107:37: note: 'std::end' declared here
107 | template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
|
I know that a ranged-based for loop is not intended to be used on an integer, and the same code (either with or without using name space std;) does not compile with clang. However, why the statement using namespace std; makes a difference when complied with GCC?
You can check this on wandbox https://wandbox.org/permlink/kp5u1iMYHST83tCa .
The reason is that there exists a method to_string in namespace std. If you rename your method to my_to_string the error message will be independent from the using statement.

How to get BOOST_FOREACH working with noncopyable rvalues?

The following code https://godbolt.org/z/X0na5H fails to compile the rvalue version of the following code. I've used the BOOST_FOREACH extensibility guidelines I found here
In short I can't seem to get boost_foreach working with noncopyabe rvalues. Is this even possible?
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
#include <vector>
struct IdentityOp : std::vector<int>, boost::noncopyable {
IdentityOp(std::vector<int> && v):std::vector<int>(std::move(v)){}
};
namespace boost { namespace foreach
{
template <>
struct is_noncopyable< IdentityOp >
: mpl::true_
{
};
}}
#define BGS_TEST_LVALUE
// At global scope...
inline boost::mpl::true_ *
boost_foreach_is_noncopyable( IdentityOp *&, boost::foreach::tag )
{
return 0;
}
int main(){
std::vector<int> v;
#ifdef BGS_TEST_LVALUE
// LVALUE VERSION
IdentityOp op(std::move(v));
BOOST_FOREACH(const auto & a, op)
#else
// RVALUE VERSION
BOOST_FOREACH(const auto & a, IdentityOp(std::move(v)))
#endif
{}
}
shows the problem. If I define BGS_TEST_LVALUE then the code compiles. If I don't define it I get the error.
In file included from <source>:2:
/celibs/boost_1_70_0/boost/foreach.hpp: In instantiation of 'boost::foreach_detail_::auto_any<T> boost::foreach_detail_::contain(const T&, mpl_::true_*) [with T = IdentityOp; mpl_::true_ = mpl_::bool_<true>]':
<source>:34:5: required from here
/celibs/boost_1_70_0/boost/foreach.hpp:632:25: error: use of deleted function 'boost::foreach_detail_::auto_any<IdentityOp>::auto_any(boost::foreach_detail_::auto_any<IdentityOp>&&)'
632 | return auto_any<T>(t);
| ^
/celibs/boost_1_70_0/boost/foreach.hpp:253:8: note: 'boost::foreach_detail_::auto_any<IdentityOp>::auto_any(boost::foreach_detail_::auto_any<IdentityOp>&&)' is implicitly deleted because the default definition would be ill-formed:
253 | struct auto_any : auto_any_base
| ^~~~~~~~
/celibs/boost_1_70_0/boost/foreach.hpp:253:8: error: call of overloaded 'IdentityOp(IdentityOp)' is ambiguous
<source>:8:5: note: candidate: 'IdentityOp::IdentityOp(std::vector<int>&&)'
8 | IdentityOp(std::vector<int> && v):std::vector<int>(std::move(v)){}
| ^~~~~~~~~~
<source>:7:9: note: candidate: 'IdentityOp::IdentityOp(const IdentityOp&)' <deleted>
7 | struct IdentityOp : std::vector<int>, boost::noncopyable {
| ^~~~~~~~~~
<source>:7:9: note: candidate: 'IdentityOp::IdentityOp(IdentityOp&&)' <deleted>
In file included from <source>:2:
/celibs/boost_1_70_0/boost/foreach.hpp: In instantiation of 'boost::foreach_detail_::auto_any<T>::auto_any(const T&) [with T = IdentityOp]':
/celibs/boost_1_70_0/boost/foreach.hpp:632:12: required from 'boost::foreach_detail_::auto_any<T> boost::foreach_detail_::contain(const T&, mpl_::true_*) [with T = IdentityOp; mpl_::true_ = mpl_::bool_<true>]'
<source>:34:5: required from here
/celibs/boost_1_70_0/boost/foreach.hpp:256:15: error: use of deleted function 'IdentityOp::IdentityOp(const IdentityOp&)'
256 | : item(t)
| ^
<source>:7:9: note: 'IdentityOp::IdentityOp(const IdentityOp&)' is implicitly deleted because the default definition would be ill-formed:
7 | struct IdentityOp : std::vector<int>, boost::noncopyable {
| ^~~~~~~~~~
<source>:7:9: error: use of deleted function 'boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)'
In file included from /celibs/boost_1_70_0/boost/noncopyable.hpp:15,
from /celibs/boost_1_70_0/boost/foreach.hpp:72,
from <source>:2:
/celibs/boost_1_70_0/boost/core/noncopyable.hpp:49:7: note: declared here
49 | noncopyable( const noncopyable& ) = delete;
| ^~~~~~~~~~~
Compiler returned: 1
https://godbolt.org/z/X0na5H