Boost.Iostreams stream can't forward 4 constructor arguments - c++

I'm trying to create a custom std::istream using Boost's stream class. It's supposed to be easier than manually creating a std::streambuf but I've hit a roadblock.
Constructing a stream requires a source object. stream has a set of forwarding constructors that take a list of arguments and forward them to the source's constructor—that's what I want to use.
// Forwarding constructors
template<typename U>
stream([const] U& u);
template<typename U1, typename U2>
stream([const] U1& u1, const U2& u2);
...
template<typename U1, ..., typename UN>
stream([const] U1& u1, const U2& u2, ..., const UN& uN);
Each of these members constructs an instance of stream and associates it with an instance of the Device T constructed from the given lists of arguments. The T constructors involved must take all arguments by value or const reference.
It works great with three arguments:
#include <memory>
#include <boost/iostreams/stream.hpp>
namespace io = boost::iostreams;
class IoSource: public io::source {
public:
IoSource(int foo, int bar, int baz) { }
std::streamsize read(char *buffer, std::streamsize n) { return -1; }
};
int main() {
auto stream = std::make_unique<io::stream<IoSource>>(1, 2, 3);
}
Result:
$ g++ -Wall -Werror -std=gnu++20 test.cpp -o /dev/null
The same program with four arguments fails to compile with a barrage of template errors:
#include <memory>
#include <boost/iostreams/stream.hpp>
namespace io = boost::iostreams;
class IoSource: public io::source {
public:
IoSource(int foo, int bar, int baz, int quux) { }
std::streamsize read(char *buffer, std::streamsize n) { return -1; }
};
int main() {
auto stream = std::make_unique<io::stream<IoSource>>(1, 2, 3, 4);
}
Result:
$ g++ -Wall -Werror -std=gnu++20 test.cpp -o /dev/null
In file included from /usr/include/c++/10/memory:83,
from test.cpp:1:
/usr/include/c++/10/bits/unique_ptr.h: In instantiation of 'typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = boost::iostreams::stream<IoSource>; _Args = {int, int, int, int}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<boost::iostreams::stream<IoSource>, std::default_delete<boost::iostreams::stream<IoSource> > >]':
test.cpp:14:68: required from here
/usr/include/c++/10/bits/unique_ptr.h:962:30: error: no matching function for call to 'boost::iostreams::stream<IoSource>::stream(int, int, int, int)'
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/preprocessor/tuple/elem.hpp:23,
from /usr/include/boost/preprocessor/repetition/enum_binary_params.hpp:19,
from /usr/include/boost/iostreams/detail/forward.hpp:22,
from /usr/include/boost/iostreams/stream.hpp:18,
from test.cpp:3:
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'boost::iostreams::stream<Device, Tr, Alloc>::stream(U100&, const U0&, const U1&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = int; U0 = int; U1 = int; Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>; typename boost::disable_if<boost::is_same<U0, T> >::type = void]' (near match)
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: conversion of argument 4 would be ill-formed:
In file included from /usr/include/c++/10/memory:83,
from test.cpp:1:
/usr/include/c++/10/bits/unique_ptr.h:962:30: error: invalid conversion from 'int' to 'boost::disable_if_c<false, void>::type*' {aka 'void*'} [-fpermissive]
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| int
In file included from /usr/include/boost/preprocessor/tuple/elem.hpp:23,
from /usr/include/boost/preprocessor/repetition/enum_binary_params.hpp:19,
from /usr/include/boost/iostreams/detail/forward.hpp:22,
from /usr/include/boost/iostreams/stream.hpp:18,
from test.cpp:3:
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'boost::iostreams::stream<Device, Tr, Alloc>::stream(const U0&, const U1&, const U2&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U0 = int; U1 = int; U2 = int; Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>; typename boost::disable_if<boost::is_same<U0, T> >::type = void]' (near match)
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: conversion of argument 4 would be ill-formed:
In file included from /usr/include/c++/10/memory:83,
from test.cpp:1:
/usr/include/c++/10/bits/unique_ptr.h:962:30: error: invalid conversion from 'int' to 'boost::disable_if_c<false, void>::type*' {aka 'void*'} [-fpermissive]
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| int
In file included from /usr/include/boost/preprocessor/tuple/elem.hpp:23,
from /usr/include/boost/preprocessor/repetition/enum_binary_params.hpp:19,
from /usr/include/boost/iostreams/detail/forward.hpp:22,
from /usr/include/boost/iostreams/stream.hpp:18,
from test.cpp:3:
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'template<class U100, class U0> boost::iostreams::stream<Device, Tr, Alloc>::stream(U100&, const U0&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = U100; U0 = U0; Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>]'
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/10/memory:83,
from test.cpp:1:
/usr/include/c++/10/bits/unique_ptr.h:962:30: note: candidate expects 3 arguments, 4 provided
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/preprocessor/tuple/elem.hpp:23,
from /usr/include/boost/preprocessor/repetition/enum_binary_params.hpp:19,
from /usr/include/boost/iostreams/detail/forward.hpp:22,
from /usr/include/boost/iostreams/stream.hpp:18,
from test.cpp:3:
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'template<class U0, class U1> boost::iostreams::stream<Device, Tr, Alloc>::stream(const U0&, const U1&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U0 = U0; U1 = U1; Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>]'
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/10/memory:83,
from test.cpp:1:
/usr/include/c++/10/bits/unique_ptr.h:962:30: note: candidate expects 3 arguments, 4 provided
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/preprocessor/tuple/elem.hpp:23,
from /usr/include/boost/preprocessor/repetition/enum_binary_params.hpp:19,
from /usr/include/boost/iostreams/detail/forward.hpp:22,
from /usr/include/boost/iostreams/stream.hpp:18,
from test.cpp:3:
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'template<class U100> boost::iostreams::stream<Device, Tr, Alloc>::stream(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = U100; Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>]'
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/10/memory:83,
from test.cpp:1:
/usr/include/c++/10/bits/unique_ptr.h:962:30: note: candidate expects 2 arguments, 4 provided
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/preprocessor/tuple/elem.hpp:23,
from /usr/include/boost/preprocessor/repetition/enum_binary_params.hpp:19,
from /usr/include/boost/iostreams/detail/forward.hpp:22,
from /usr/include/boost/iostreams/stream.hpp:18,
from test.cpp:3:
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'template<class U0> boost::iostreams::stream<Device, Tr, Alloc>::stream(const U0&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U0 = U0; Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>]'
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/10/memory:83,
from test.cpp:1:
/usr/include/c++/10/bits/unique_ptr.h:962:30: note: candidate expects 2 arguments, 4 provided
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/iostreams/stream.hpp:18,
from test.cpp:3:
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'boost::iostreams::stream<Device, Tr, Alloc>::stream(const boost::reference_wrapper<T>&, std::streamsize, std::streamsize) [with Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>; std::streamsize = long int]'
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate expects 3 arguments, 4 provided
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'boost::iostreams::stream<Device, Tr, Alloc>::stream(Device&, std::streamsize, std::streamsize) [with Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>; std::streamsize = long int]'
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate expects 3 arguments, 4 provided
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate: 'boost::iostreams::stream<Device, Tr, Alloc>::stream(const Device&, std::streamsize, std::streamsize) [with Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>; std::streamsize = long int]'
144 | BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device,
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/stream.hpp:144:5: note: candidate expects 3 arguments, 4 provided
In file included from test.cpp:3:
/usr/include/boost/iostreams/stream.hpp:143:5: note: candidate: 'boost::iostreams::stream<Device, Tr, Alloc>::stream() [with Device = IoSource; Tr = std::char_traits<char>; Alloc = std::allocator<char>]'
143 | stream() { }
| ^~~~~~
/usr/include/boost/iostreams/stream.hpp:143:5: note: candidate expects 0 arguments, 4 provided
What am I doing wrong? I believe I've narrowed this down to the core problem. It seems to be purely an issue with the number of arguments; it doesn't matter if they're values or const references, nor do their types matter.
Boost 1.78
g++ (Debian 10.2.1-6) 10.2.1 20210110

Boost doesn't use variadic templates and perfect forwarding to forward arguments. It uses preprocessor macros to simulate varargs, macros which have a maximum arity:
boost/iostreams/detail/config/limits.hpp
#ifndef BOOST_IOSTREAMS_MAX_FORWARDING_ARITY
# define BOOST_IOSTREAMS_MAX_FORWARDING_ARITY 3
#endif
The number of arguments can be increased by defining the macro above before including Boost's headers:
#define BOOST_IOSTREAMS_MAX_FORWARDING_ARITY 4
#include <boost/iostreams/stream.hpp>

Related

How to use a C++20 istream_view?

I cannot find a single example on the web or in C++20 books that shows how the results of a std::ranges::istream_view can be used with follow-up operations. Every follow-up operation that I try to use results in compiler errors that are too difficult for me to figure out alone.
For example, how should I split a lazy stream of characters that comes in through an istream_view? The following code does not work, but hopefully communicates what I am trying to achieve:
#include <cstdlib>
#include <ranges>
#include <sstream>
#include <fmt/core.h>
auto main() -> int
{
std::istringstream data{"a,b"};
for (const auto& item:
std::views::istream<std::string>(data)
| std::views::split(",")
) {
fmt::print("{}\n", item);
}
return EXIT_SUCCESS;
}
^ I expect this to write "a" on the first line, and "b" on the second line.
GCC 12.2 emits an intimidating error message:
Could not execute the program
Compiler returned: 1
Compiler stderr
<source>: In function 'int main()':
<source>:11:5: error: no match for 'operator|' (operand types are 'std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >' and 'std::ranges::views::__adaptor::_Partial<std::ranges::views::_Split, const char*>')
10 | std::views::istream<std::string>(data)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >
11 | | std::views::split(",")
| ^ ~~~~~~~~~~~~~~~~~~~~~~
| |
| std::ranges::views::__adaptor::_Partial<std::ranges::views::_Split, const char*>
In file included from <source>:2:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:868:7: note: candidate: 'template<class _Lhs, class _Rhs> requires (derived_from<_Lhs, std::ranges::views::__adaptor::_RangeAdaptorClosure>) && (derived_from<_Rhs, std::ranges::views::__adaptor::_RangeAdaptorClosure>) constexpr auto std::ranges::views::__adaptor::operator|(_Lhs, _Rhs)'
868 | operator|(_Lhs __lhs, _Rhs __rhs)
| ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:868:7: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:868:7: note: constraints not satisfied
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:37:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/concepts: In substitution of 'template<class _Lhs, class _Rhs> requires (derived_from<_Lhs, std::ranges::views::__adaptor::_RangeAdaptorClosure>) && (derived_from<_Rhs, std::ranges::views::__adaptor::_RangeAdaptorClosure>) constexpr auto std::ranges::views::__adaptor::operator|(_Lhs, _Rhs) [with _Lhs = std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >; _Rhs = std::ranges::views::__adaptor::_Partial<std::ranges::views::_Split, const char*>]':
<source>:11:28: required from here
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/concepts:67:13: required for the satisfaction of 'derived_from<_Lhs, std::ranges::views::__adaptor::_RangeAdaptorClosure>' [with _Lhs = std::ranges::basic_istream_view<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char, std::char_traits<char> >]
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/concepts:67:28: note: 'std::ranges::views::__adaptor::_RangeAdaptorClosure' is not a base of 'std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >'
67 | concept derived_from = __is_base_of(_Base, _Derived)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:859:7: note: candidate: 'template<class _Self, class _Range> requires (derived_from<typename std::remove_cvref<_Tp>::type, std::ranges::views::__adaptor::_RangeAdaptorClosure>) && (__adaptor_invocable<_Self, _Range>) constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, _Self&&)'
859 | operator|(_Range&& __r, _Self&& __self)
| ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:859:7: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:859:7: note: constraints not satisfied
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges: In substitution of 'template<class _Self, class _Range> requires (derived_from<typename std::remove_cvref<_Tp>::type, std::ranges::views::__adaptor::_RangeAdaptorClosure>) && (__adaptor_invocable<_Self, _Range>) constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, _Self&&) [with _Self = std::ranges::views::__adaptor::_Partial<std::ranges::views::_Split, const char*>; _Range = std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >]':
<source>:11:28: required from here
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:831:13: required for the satisfaction of '__adaptor_invocable<_Self, _Range>' [with _Self = std::ranges::views::__adaptor::_Partial<std::ranges::views::_Split, const char*>; _Range = std::ranges::basic_istream_view<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char, std::char_traits<char> >]
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:832:9: in requirements [with _Args = {std::ranges::basic_istream_view<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char, std::char_traits<char> >}; _Adaptor = std::ranges::views::__adaptor::_Partial<std::ranges::views::_Split, const char*>]
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:832:44: note: the required expression 'declval<_Adaptor>()((declval<_Args>)()...)' is invalid
832 | = requires { std::declval<_Adaptor>()(declval<_Args>()...); };
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/streambuf:41,
from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/streambuf_iterator.h:35,
from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/iterator:66,
from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:43:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/ios_base.h:87:3: note: candidate: 'constexpr std::_Ios_Fmtflags std::operator|(_Ios_Fmtflags, _Ios_Fmtflags)'
87 | operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
| ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/ios_base.h:87:27: note: no known conversion for argument 1 from 'std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >' to 'std::_Ios_Fmtflags'
87 | operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
| ~~~~~~~~~~~~~~^~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/ios_base.h:130:3: note: candidate: 'constexpr std::_Ios_Openmode std::operator|(_Ios_Openmode, _Ios_Openmode)'
130 | operator|(_Ios_Openmode __a, _Ios_Openmode __b)
| ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/ios_base.h:130:27: note: no known conversion for argument 1 from 'std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >' to 'std::_Ios_Openmode'
130 | operator|(_Ios_Openmode __a, _Ios_Openmode __b)
| ~~~~~~~~~~~~~~^~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/ios_base.h:170:3: note: candidate: 'constexpr std::_Ios_Iostate std::operator|(_Ios_Iostate, _Ios_Iostate)'
170 | operator|(_Ios_Iostate __a, _Ios_Iostate __b)
| ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/ios_base.h:170:26: note: no known conversion for argument 1 from 'std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >' to 'std::_Ios_Iostate'
170 | operator|(_Ios_Iostate __a, _Ios_Iostate __b)
| ~~~~~~~~~~~~~^~~
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/span:42,
from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:45:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/cstddef:132:3: note: candidate: 'constexpr std::byte std::operator|(byte, byte)'
132 | operator|(byte __l, byte __r) noexcept
| ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/cstddef:132:18: note: no known conversion for argument 1 from 'std::ranges::basic_istream_view<std::__cxx11::basic_string<char>, char, std::char_traits<char> >' to 'std::byte'
132 | operator|(byte __l, byte __r) noexcept
| ~~~~~^~~
views::istream is an input range. So any adaptor that you pipe that into has to work on input ranges. views::split requires forward-or-better, which is why you can't split an istream.
But there is also a views::lazy_split that provides a slight differently interface such that it does work for input ranges (see P2210 for added context for why we wanted the forward+ split adaptor).
However, then you have the issue that views::istream<string> is a range of string that you're trying split on a comma. But that's not quite right, what you want you want is a range of char so that you end up with a range of range of char. What you mean is views::istream<char>.
Fixing that, this works:
auto main() -> int
{
std::istringstream data{"a,b"};
fmt::print("{}\n",
std::views::istream<char>(data)
| std::views::lazy_split(','));
}
That prints [['a'], ['b']]

error: no matching function for call to ‘std::tuple<synchronizer>::tuple(<brace-enclosed initializer list>)’

I'm getting a really big, scary, puzzling error in some code I've been working on lately. Basically, I'm trying to declare a thread and put it inside a std::vector for safe keeping. However, for some reason this gets std::tuple involved, which doesn't like what I'm doing.
How do I fix this?
P.S. I've already looked at this. If the answer's there, I'm not seeing it.
synchronizer.cpp:
#include <sys/socket.h>
#include <vector>
#include <thread>
#include <iostream>
#define PACKET_SIZE 8192
class synchronizer
{
private:
int sock;
int* status;
public:
int start();
synchronizer(int socket, int* stat);
~synchronizer();
void operator()();
};
synchronizer::synchronizer(int socket, int* stat) : sock(socket), status(stat) {}
void synchronizer::operator()()
{
this->start();
}
int synchronizer::start()
{
std::cout << "Starting." << std::endl;
char buf[PACKET_SIZE];
if (recv(sock, buf, PACKET_SIZE, 0) == -1)
{
perror("Error receiving");
return -1;
}
return 0;
}
synchronizer::~synchronizer()
{
}
The relevant bits of server.cpp, which is the main file:
#include <iostream>
#include <thread>
#include "synchronizer.hpp"
inline int checkin (std::vector<std::thread> *pool, int conn, int *status)
{
synchronizer syncer = synchronizer(conn, status);
pool->push_back(std::thread(syncer));
return 0;
}
int main(void)
{
std::vector<std::thread> pool = {};
int status = 0;
// newfd being a socket file descriptor acquired earlier in the program's logic
checkin(&pool, newfd, &status);
}
And here's the error (compiling with option -pthread):
In file included from server.cpp:14:
/usr/include/c++/9/thread: In instantiation of ‘static std::thread::_Invoker<std::tuple<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...> > std::thread::__make_invoker(_Callable&&, _Args&& ...) [with _Callable = synchronizer&; _Args = {}; typename std::decay<_Tp>::type = synchronizer]’:
/usr/include/c++/9/thread:131:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = synchronizer&; _Args = {}; <template-parameter-1-3> = void]’
server.cpp:44:49: required from here
/usr/include/c++/9/thread:267:4: error: no matching function for call to ‘std::tuple<synchronizer>::tuple(<brace-enclosed initializer list>)’
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:808:11: note: candidate: ‘template<class _Alloc, class _Dummy, class ... _UElements, typename std::enable_if<((std::tuple<synchronizer>::_TMCT<_UElements ...>::_MoveConstructibleTuple<_UElements ...>() && (! std::tuple<synchronizer>::_TMCT<_UElements ...>::_ImplicitlyMoveConvertibleTuple<_UElements ...>())) && std::tuple<synchronizer>::_TNTC<_Dummy>::_NonNestedTuple<tuple<_Tail ...>&&>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, std::tuple<_Args2 ...>&&)’
808 | explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
| ^~~~~
/usr/include/c++/9/tuple:808:11: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 3 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:793:2: note: candidate: ‘template<class _Alloc, class _Dummy, class ... _UElements, typename std::enable_if<((std::tuple<synchronizer>::_TMCT<_UElements ...>::_MoveConstructibleTuple<_UElements ...>() && std::tuple<synchronizer>::_TMCT<_UElements ...>::_ImplicitlyMoveConvertibleTuple<_UElements ...>()) && std::tuple<synchronizer>::_TNTC<_Dummy>::_NonNestedTuple<tuple<_Tail ...>&&>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, std::tuple<_Args2 ...>&&)’
793 | tuple(allocator_arg_t __tag, const _Alloc& __a,
| ^~~~~
/usr/include/c++/9/tuple:793:2: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 3 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:778:11: note: candidate: ‘template<class _Alloc, class _Dummy, class ... _UElements, typename std::enable_if<((std::tuple<synchronizer>::_TMCT<_UElements ...>::_ConstructibleTuple<_UElements ...>() && (! std::tuple<synchronizer>::_TMCT<_UElements ...>::_ImplicitlyConvertibleTuple<_UElements ...>())) && std::tuple<synchronizer>::_TNTC<_Dummy>::_NonNestedTuple<const tuple<_Tail ...>&>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const std::tuple<_Args2 ...>&)’
778 | explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
| ^~~~~
/usr/include/c++/9/tuple:778:11: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 3 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:763:2: note: candidate: ‘template<class _Alloc, class _Dummy, class ... _UElements, typename std::enable_if<((std::tuple<synchronizer>::_TMCT<_UElements ...>::_ConstructibleTuple<_UElements ...>() && std::tuple<synchronizer>::_TMCT<_UElements ...>::_ImplicitlyConvertibleTuple<_UElements ...>()) && std::tuple<synchronizer>::_TNTC<_Dummy>::_NonNestedTuple<const tuple<_Tail ...>&>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const std::tuple<_Args2 ...>&)’
763 | tuple(allocator_arg_t __tag, const _Alloc& __a,
| ^~~~~
/usr/include/c++/9/tuple:763:2: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 3 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:751:2: note: candidate: ‘template<class _Alloc> std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, std::tuple<_Elements>&&)’
751 | tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
| ^~~~~
/usr/include/c++/9/tuple:751:2: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 3 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:747:2: note: candidate: ‘template<class _Alloc> std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const std::tuple<_Elements>&)’
747 | tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
| ^~~~~
/usr/include/c++/9/tuple:747:2: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 3 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:741:11: note: candidate: ‘template<class _Alloc, class ... _UElements, typename std::enable_if<(std::tuple<synchronizer>::_TMC<_UElements ...>::_MoveConstructibleTuple<_UElements ...>() && (! std::tuple<synchronizer>::_TMC<_UElements ...>::_ImplicitlyMoveConvertibleTuple<_UElements ...>())), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, _UElements&& ...)’
741 | explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
| ^~~~~
/usr/include/c++/9/tuple:741:11: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects at least 2 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:730:2: note: candidate: ‘template<class _Alloc, class ... _UElements, typename std::enable_if<(std::tuple<synchronizer>::_TMC<_UElements ...>::_MoveConstructibleTuple<_UElements ...>() && std::tuple<synchronizer>::_TMC<_UElements ...>::_ImplicitlyMoveConvertibleTuple<_UElements ...>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, _UElements&& ...)’
730 | tuple(allocator_arg_t __tag, const _Alloc& __a,
| ^~~~~
/usr/include/c++/9/tuple:730:2: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects at least 2 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:720:11: note: candidate: ‘template<class _Alloc, class _Dummy, typename std::enable_if<(std::tuple<synchronizer>::_TCC<_Dummy>::_ConstructibleTuple<synchronizer>() && (! std::tuple<synchronizer>::_TCC<_Dummy>::_ImplicitlyConvertibleTuple<synchronizer>())), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const _Elements& ...)’
720 | explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
| ^~~~~
/usr/include/c++/9/tuple:720:11: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 3 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:709:2: note: candidate: ‘template<class _Alloc, class _Dummy, typename std::enable_if<(std::tuple<synchronizer>::_TCC<_Dummy>::_ConstructibleTuple<synchronizer>() && std::tuple<synchronizer>::_TCC<_Dummy>::_ImplicitlyConvertibleTuple<synchronizer>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const _Elements& ...)’
709 | tuple(allocator_arg_t __tag, const _Alloc& __a,
| ^~~~~
/usr/include/c++/9/tuple:709:2: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 3 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:699:2: note: candidate: ‘template<class _Alloc> std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&)’
699 | tuple(allocator_arg_t __tag, const _Alloc& __a)
| ^~~~~
/usr/include/c++/9/tuple:699:2: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 2 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:693:28: note: candidate: ‘template<class ... _UElements, class _Dummy, typename std::enable_if<((std::tuple<synchronizer>::_TMCT<_UElements ...>::_MoveConstructibleTuple<_UElements ...>() && (! std::tuple<synchronizer>::_TMCT<_UElements ...>::_ImplicitlyMoveConvertibleTuple<_UElements ...>())) && std::tuple<synchronizer>::_TNTC<_Dummy>::_NonNestedTuple<tuple<_Tps ...>&&>()), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(std::tuple<_Args1 ...>&&)’
693 | explicit constexpr tuple(tuple<_UElements...>&& __in)
| ^~~~~
/usr/include/c++/9/tuple:693:28: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: ‘synchronizer’ is not derived from ‘std::tuple<_Tps ...>’
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:682:19: note: candidate: ‘template<class ... _UElements, class _Dummy, typename std::enable_if<((std::tuple<synchronizer>::_TMCT<_UElements ...>::_MoveConstructibleTuple<_UElements ...>() && std::tuple<synchronizer>::_TMCT<_UElements ...>::_ImplicitlyMoveConvertibleTuple<_UElements ...>()) && std::tuple<synchronizer>::_TNTC<_Dummy>::_NonNestedTuple<tuple<_Tps ...>&&>()), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(std::tuple<_Args1 ...>&&)’
682 | constexpr tuple(tuple<_UElements...>&& __in)
| ^~~~~
/usr/include/c++/9/tuple:682:19: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: ‘synchronizer’ is not derived from ‘std::tuple<_Tps ...>’
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:670:28: note: candidate: ‘template<class ... _UElements, class _Dummy, typename std::enable_if<((std::tuple<synchronizer>::_TMCT<_UElements ...>::_ConstructibleTuple<_UElements ...>() && (! std::tuple<synchronizer>::_TMCT<_UElements ...>::_ImplicitlyConvertibleTuple<_UElements ...>())) && std::tuple<synchronizer>::_TNTC<_Dummy>::_NonNestedTuple<const tuple<_Tps ...>&>()), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(const std::tuple<_Args1 ...>&)’
670 | explicit constexpr tuple(const tuple<_UElements...>& __in)
| ^~~~~
/usr/include/c++/9/tuple:670:28: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: ‘synchronizer’ is not derived from ‘const std::tuple<_Tps ...>’
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:658:19: note: candidate: ‘template<class ... _UElements, class _Dummy, typename std::enable_if<((std::tuple<synchronizer>::_TMCT<_UElements ...>::_ConstructibleTuple<_UElements ...>() && std::tuple<synchronizer>::_TMCT<_UElements ...>::_ImplicitlyConvertibleTuple<_UElements ...>()) && std::tuple<synchronizer>::_TNTC<_Dummy>::_NonNestedTuple<const tuple<_Tps ...>&>()), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(const std::tuple<_Args1 ...>&)’
658 | constexpr tuple(const tuple<_UElements...>& __in)
| ^~~~~
/usr/include/c++/9/tuple:658:19: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: ‘synchronizer’ is not derived from ‘const std::tuple<_Tps ...>’
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:642:17: note: candidate: ‘constexpr std::tuple<_Elements>::tuple(std::tuple<_Elements>&&) [with _Elements = {synchronizer}]’
642 | constexpr tuple(tuple&&) = default;
| ^~~~~
/usr/include/c++/9/tuple:642:23: note: no known conversion for argument 1 from ‘synchronizer’ to ‘std::tuple<synchronizer>&&’
642 | constexpr tuple(tuple&&) = default;
| ^~~~~~~
/usr/include/c++/9/tuple:637:28: note: candidate: ‘template<class ... _UElements, typename std::enable_if<((std::tuple<synchronizer>::_TMC<_UElements ...>::_MoveConstructibleTuple<_UElements ...>() && (! std::tuple<synchronizer>::_TMC<_UElements ...>::_ImplicitlyMoveConvertibleTuple<_UElements ...>())) && (1 >= 1)), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(_UElements&& ...)’
637 | explicit constexpr tuple(_UElements&&... __elements)
| ^~~~~
/usr/include/c++/9/tuple:637:28: note: template argument deduction/substitution failed:
/usr/include/c++/9/tuple:636:21: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
636 | bool>::type=false>
| ^~~~~
/usr/include/c++/9/tuple:626:19: note: candidate: ‘template<class ... _UElements, typename std::enable_if<((std::tuple<synchronizer>::_TMC<_UElements ...>::_MoveConstructibleTuple<_UElements ...>() && std::tuple<synchronizer>::_TMC<_UElements ...>::_ImplicitlyMoveConvertibleTuple<_UElements ...>()) && (1 >= 1)), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(_UElements&& ...)’
626 | constexpr tuple(_UElements&&... __elements)
| ^~~~~
/usr/include/c++/9/tuple:626:19: note: template argument deduction/substitution failed:
/usr/include/c++/9/tuple:625:21: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
625 | bool>::type=true>
| ^~~~
/usr/include/c++/9/tuple:599:26: note: candidate: ‘template<class _Dummy, typename std::enable_if<((std::tuple<synchronizer>::_TCC<_Dummy>::_ConstructibleTuple<synchronizer>() && (! std::tuple<synchronizer>::_TCC<_Dummy>::_ImplicitlyConvertibleTuple<synchronizer>())) && (1 >= 1)), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(const _Elements& ...)’
599 | explicit constexpr tuple(const _Elements&... __elements)
| ^~~~~
/usr/include/c++/9/tuple:599:26: note: template argument deduction/substitution failed:
/usr/include/c++/9/tuple:598:28: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
598 | bool>::type=false>
| ^~~~~
/usr/include/c++/9/tuple:588:19: note: candidate: ‘template<class _Dummy, typename std::enable_if<((std::tuple<synchronizer>::_TCC<_Dummy>::_ConstructibleTuple<synchronizer>() && std::tuple<synchronizer>::_TCC<_Dummy>::_ImplicitlyConvertibleTuple<synchronizer>()) && (1 >= 1)), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(const _Elements& ...)’
588 | constexpr tuple(const _Elements&... __elements)
| ^~~~~
/usr/include/c++/9/tuple:588:19: note: template argument deduction/substitution failed:
/usr/include/c++/9/tuple:587:28: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
587 | bool>::type=true>
| ^~~~
/usr/include/c++/9/tuple:571:26: note: candidate: ‘template<class _Dummy, typename std::enable_if<(std::tuple<synchronizer>::_TC2<_Dummy>::_DefaultConstructibleTuple() && (! std::tuple<synchronizer>::_TC2<_Dummy>::_ImplicitlyDefaultConstructibleTuple())), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple()’
571 | explicit constexpr tuple()
| ^~~~~
/usr/include/c++/9/tuple:571:26: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 0 arguments, 1 provided
267 | } };
| ^
In file included from /usr/include/c++/9/bits/unique_ptr.h:37,
from /usr/include/c++/9/memory:80,
from /usr/include/c++/9/thread:39,
from server.cpp:14:
/usr/include/c++/9/tuple:561:17: note: candidate: ‘template<class _Dummy, typename std::enable_if<std::tuple<synchronizer>::_TC2<_Dummy>::_ImplicitlyDefaultConstructibleTuple(), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple()’
561 | constexpr tuple()
| ^~~~~
/usr/include/c++/9/tuple:561:17: note: template argument deduction/substitution failed:
In file included from server.cpp:14:
/usr/include/c++/9/thread:267:4: note: candidate expects 0 arguments, 1 provided
267 | } };
| ^
/usr/include/c++/9/thread:267:4: error: could not convert ‘{<expression error>}’ from ‘<brace-enclosed initializer list>’ to ‘std::thread::_Invoker<std::tuple<synchronizer> >’

std::multiset intersection compilation error

I'm trying to find the intersection of 2 multisets of objects using std::set_intersection function.
#include <algorithm>
#include <set>
struct Interval
{
double bottom;
double top;
};
struct cmp_interval
{
bool operator()(Interval a, Interval b) const
{
return a.bottom < b.bottom;
}
}
int main()
{
std::multiset<Interval, cmp_interval> I1;
Interval i;
i.bottom = 20;
i.top = 30;
I1.insert(i);
std::multiset<Interval, cmp_interval> I2;
I2.insert(i);
std::multiset<Interval, cmp_interval> I3;
std::set_intersection(I1.begin(), I1.end(), I2.begin(), I2.end(), std::inserter(I3, I3.begin()));
return 0;
}
When I try to compile it, i get a page of verbose errors that I'm unable to properly understand. I'm still a novice in c++ although i do understand some fundamental concepts. Below is the error log generated,
Starting build...
/usr/bin/g++ -g /home/jamal/Documents/daa_assignment_1/measure.cpp -o /home/jamal/Documents/daa_assignment_1/measure
In file included from /usr/include/c++/9/bits/stl_algobase.h:71,
from /usr/include/c++/9/bits/char_traits.h:39,
from /usr/include/c++/9/ios:40,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/predefined_ops.h: In instantiation of ‘constexpr bool __gnu_cxx::__ops::_Iter_less_iter::operator()(_Iterator1, _Iterator2) const [with _Iterator1 = std::_Rb_tree_const_iterator<Interval>; _Iterator2 = std::_Rb_tree_const_iterator<Interval>]’:
/usr/include/c++/9/bits/stl_algo.h:5252:12: required from ‘_OutputIterator std::__set_intersection(_InputIterator1, _InputIterator1, _InputIterator2, _InputIterator2, _OutputIterator, _Compare) [with _InputIterator1 = std::_Rb_tree_const_iterator<Interval>; _InputIterator2 = std::_Rb_tree_const_iterator<Interval>; _OutputIterator = std::insert_iterator<std::multiset<Interval, cmp_interval> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/9/bits/stl_algo.h:5307:48: required from ‘_OIter std::set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter) [with _IIter1 = std::_Rb_tree_const_iterator<Interval>; _IIter2 = std::_Rb_tree_const_iterator<Interval>; _OIter = std::insert_iterator<std::multiset<Interval, cmp_interval> >]’
/home/jamal/Documents/daa_assignment_1/measure.cpp:338:100: required from here
/usr/include/c++/9/bits/predefined_ops.h:43:23: error: no match for ‘operator<’ (operand types are ‘const Interval’ and ‘const Interval’)
43 | { return *__it1 < *__it2; }
| ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/9/bits/stl_algobase.h:67,
from /usr/include/c++/9/bits/char_traits.h:39,
from /usr/include/c++/9/ios:40,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/stl_iterator.h:915:5: note: candidate: ‘template<class _IteratorL, class _IteratorR, class _Container> bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_IteratorL, _Container>&, const __gnu_cxx::__normal_iterator<_IteratorR, _Container>&)’
915 | operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
| ^~~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:915:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/9/bits/stl_algobase.h:71,
from /usr/include/c++/9/bits/char_traits.h:39,
from /usr/include/c++/9/ios:40,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/predefined_ops.h:43:23: note: ‘const Interval’ is not derived from ‘const __gnu_cxx::__normal_iterator<_IteratorL, _Container>’
43 | { return *__it1 < *__it2; }
| ~~~~~~~^~~~~~~~
In file included from /usr/include/c++/9/bits/stl_algobase.h:67,
from /usr/include/c++/9/bits/char_traits.h:39,
from /usr/include/c++/9/ios:40,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/stl_iterator.h:922:5: note: candidate: ‘template<class _Iterator, class _Container> bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_Iterator, _Container>&, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&)’
922 | operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
| ^~~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:922:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/9/bits/stl_algobase.h:71,
from /usr/include/c++/9/bits/char_traits.h:39,
from /usr/include/c++/9/ios:40,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from /home/jamal/Documents/daa_assignment_1/measure.cpp:1:
/usr/include/c++/9/bits/predefined_ops.h:43:23: note: ‘const Interval’ is not derived from ‘const __gnu_cxx::__normal_iterator<_Iterator, _Container>’
43 | { return *__it1 < *__it2; }
| ~~~~~~~^~~~~~~~
Build finished with error(s).
The terminal process failed to launch (exit code: -1).
Any help would be appreciated. Thank you.
Update:
From the error log, I see that there's another optional argument that needs to be passed for std::set_intersection for custom comparator.
/usr/include/c++/9/bits/stl_algo.h:5252:12: required from ‘_OutputIterator std::__set_intersection(_InputIterator1, _InputIterator1, _InputIterator2, _InputIterator2, _OutputIterator, _Compare) [with _InputIterator1 = std::_Rb_tree_const_iterator<Interval>; _InputIterator2 = std::_Rb_tree_const_iterator<Interval>; _OutputIterator = std::insert_iterator<std::multiset<Interval, cmp_interval> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
The _Compare parameter looks to be by default
__gnu_cxx::__ops::_Iter_less_iter. I want to use comparator class that i have made(cmp_interval) there but it doesn't accept classes.
std::multiset<Interval, cmp_interval> I3;
Here, you specify the type of the comparator, as a type template argument. The actual comparator object is created inside the constructor of the multiset. Now you want to pass a similar object to the std::set_intersection function. Use:
std::set_intersection(I1.begin(), I1.end(),
I2.begin(), I2.end(),
std::inserter(I3, I3.begin()),
cmp_interval());
The empty parenthesis in cmp_interval() mean: an unnamed default-constructed object. You could also use cmp_interval{}, since C++11.

Why type unsigned makes std::variant<int64_t,uint64_t> ambiguous to construct?

I'd like to use simply unsigned(123) and 123u rather than 123ul and (unsigned long)(123).
#include <cstdint>
#include <variant>
using namespace std;
int main()
{
using var_t = variant<int64_t,uint64_t,double>;
var_t v1{1};
var_t v2{1ul};
var_t v3{1u}; //ERROR
// var_t v4{unsigned(1)}; //ERROR
var_t v5{uint64_t(1)};
}
live example
Compiler output
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'int main()':
main.cpp:10:15: error: no matching function for call to 'std::variant<long int, long unsigned int, double>::variant(<brace-enclosed initializer list>)'
10 | var_t v3{1u}; //ERROR
| ^
In file included from main.cpp:2:
/usr/local/include/c++/10.2.0/variant:1402:2: note: candidate: 'template<long unsigned int _Np, class _Up, class ... _Args, class _Tp, class> constexpr std::variant<_Types>::variant(std::in_place_index_t<_Np>, std::initializer_list<_Up>, _Args&& ...) [with long unsigned int _Np = _Np; _Up = _Up; _Args = {_Args ...}; _Tp = _Tp; <template-parameter-2-5> = <template-parameter-1-5>; _Types = {long int, long unsigned int, double}]'
1402 | variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
| ^~~~~~~
/usr/local/include/c++/10.2.0/variant:1402:2: note: template argument deduction/substitution failed:
main.cpp:10:15: note: mismatched types 'std::in_place_index_t<_Idx>' and 'unsigned int'
10 | var_t v3{1u}; //ERROR
| ^
In file included from main.cpp:2:
/usr/local/include/c++/10.2.0/variant:1391:2: note: candidate: 'template<long unsigned int _Np, class ... _Args, class _Tp, class> constexpr std::variant<_Types>::variant(std::in_place_index_t<_Np>, _Args&& ...) [with long unsigned int _Np = _Np; _Args = {_Args ...}; _Tp = _Tp; <template-parameter-2-4> = <template-parameter-1-4>; _Types = {long int, long unsigned int, double}]'
1391 | variant(in_place_index_t<_Np>, _Args&&... __args)
| ^~~~~~~
/usr/local/include/c++/10.2.0/variant:1391:2: note: template argument deduction/substitution failed:
main.cpp:10:15: note: mismatched types 'std::in_place_index_t<_Idx>' and 'unsigned int'
10 | var_t v3{1u}; //ERROR
| ^
In file included from main.cpp:2:
/usr/local/include/c++/10.2.0/variant:1381:2: note: candidate: 'template<class _Tp, class _Up, class ... _Args, class> constexpr std::variant<_Types>::variant(std::in_place_type_t<_Tp>, std::initializer_list<_Up>, _Args&& ...) [with _Tp = _Tp; _Up = _Up; _Args = {_Args ...}; <template-parameter-2-4> = <template-parameter-1-4>; _Types = {long int, long unsigned int, double}]'
1381 | variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
| ^~~~~~~
/usr/local/include/c++/10.2.0/variant:1381:2: note: template argument deduction/substitution failed:
main.cpp:10:15: note: mismatched types 'std::in_place_type_t<_Tp>' and 'unsigned int'
10 | var_t v3{1u}; //ERROR
| ^
In file included from main.cpp:2:
/usr/local/include/c++/10.2.0/variant:1371:2: note: candidate: 'template<class _Tp, class ... _Args, class> constexpr std::variant<_Types>::variant(std::in_place_type_t<_Tp>, _Args&& ...) [with _Tp = _Tp; _Args = {_Args ...}; <template-parameter-2-3> = <template-parameter-1-3>; _Types = {long int, long unsigned int, double}]'
1371 | variant(in_place_type_t<_Tp>, _Args&&... __args)
| ^~~~~~~
/usr/local/include/c++/10.2.0/variant:1371:2: note: template argument deduction/substitution failed:
main.cpp:10:15: note: mismatched types 'std::in_place_type_t<_Tp>' and 'unsigned int'
10 | var_t v3{1u}; //ERROR
| ^
In file included from main.cpp:2:
/usr/local/include/c++/10.2.0/variant:1361:2: note: candidate: 'template<class _Tp, class, class, class _Tj, class> constexpr std::variant<_Types>::variant(_Tp&&) [with _Tp = _Tp; <template-parameter-2-2> = <template-parameter-1-2>; <template-parameter-2-3> = <template-parameter-1-3>; _Tj = _Tj; <template-parameter-2-5> = <template-parameter-1-5>; _Types = {long int, long unsigned int, double}]'
1361 | variant(_Tp&& __t)
| ^~~~~~~
/usr/local/include/c++/10.2.0/variant:1361:2: note: template argument deduction/substitution failed:
/usr/local/include/c++/10.2.0/variant: In substitution of 'template<class ... _Types> template<class _Tp, class> using __accepted_type = std::variant<_Types>::__to_type<__accepted_index<_Tp> > [with _Tp = unsigned int&&; <template-parameter-2-2> = void; _Types = {long int, long unsigned int, double}]':
/usr/local/include/c++/10.2.0/variant:1357:9: required from here
/usr/local/include/c++/10.2.0/variant:1327:8: error: no type named 'type' in 'struct std::enable_if<false, void>'
1327 | using __accepted_type = __to_type<__accepted_index<_Tp>>;
| ^~~~~~~~~~~~~~~
/usr/local/include/c++/10.2.0/variant:1349:7: note: candidate: 'constexpr std::variant<_Types>::variant(std::variant<_Types>&&) [with _Types = {long int, long unsigned int, double}]'
1349 | variant(variant&&) = default;
| ^~~~~~~
/usr/local/include/c++/10.2.0/variant:1349:15: note: no known conversion for argument 1 from 'unsigned int' to 'std::variant<long int, long unsigned int, double>&&'
1349 | variant(variant&&) = default;
| ^~~~~~~~~
/usr/local/include/c++/10.2.0/variant:1348:7: note: candidate: 'constexpr std::variant<_Types>::variant(const std::variant<_Types>&) [with _Types = {long int, long unsigned int, double}]'
1348 | variant(const variant& __rhs) = default;
| ^~~~~~~
/usr/local/include/c++/10.2.0/variant:1348:30: note: no known conversion for argument 1 from 'unsigned int' to 'const std::variant<long int, long unsigned int, double>&'
1348 | variant(const variant& __rhs) = default;
| ~~~~~~~~~~~~~~~^~~~~
/usr/local/include/c++/10.2.0/variant:1347:7: note: candidate: 'constexpr std::variant<_Types>::variant() [with _Types = {long int, long unsigned int, double}]'
1347 | variant() = default;
| ^~~~~~~
/usr/local/include/c++/10.2.0/variant:1347:7: note: candidate expects 0 arguments, 1 provided
main.cpp:10:10: warning: unused variable 'v3' [-Wunused-variable]
10 | var_t v3{1u}; //ERROR
| ^~
The final rule we landed on for variant is that we consider only alternatives where the conversion is non-narrowing, and that narrowing determination considers the type, not the value.
Among other things:
integer to floating point is always narrowing.
signed to unsigned is always narrowing.
unsigned to signed is narrowing if the signed type can't represent all possible values of the unsigned type.
So:
For v1, the source type is int, the only non-narrowing alternative is int64_t, and it is chosen.
For v2, the source type is unsigned long. If sizeof(int64_t) == sizeof(unsigned long), as is the case for many platforms, then the only non-narrowing alternative is uint64_t, and that is chosen.
For v3, the source type is unsigned int. If int is 32 bits then both int64_t and uint64_t are viable options, and neither is better than the other. So it is ambiguous.
For this kind of thing, it's a lot clearer to use in_place_type to explicitly pick which alternative you want, instead of asking the reader to do overload resolution in their head.
The answer would be platform dependent, but on my platform (64 bit linux + gcc C++) your results make perfect sense. Just note, in all below results conversion to double has lower rank than integral promotions, so it doesn't participate.
// Below works, as 1 is signed, and can only be promoted to int64_t.
variant<int64_t,uint64_t,double> v1{1};
// Below works, as 1ul is exactly unsigned long (64 bit for me), and is exact match
variant<int64_t,uint64_t,double> v2{1ul};
// Below doesn't work, as 1u is unsigned int, and can be equally promoted to int64_t and uint64_t - thus ambiguity
variant<int64_t,uint64_t,double> v3{1u}; //ERROR
// Below doesn't work, for exactly the same reason as one above.
variant<int64_t,uint64_t,double> v4{unsigned(1)}; //ERROR
}
I found an elegant solution with extending std::variant:
#include <cstdint>
#include <variant>
using namespace std;
struct var_t : variant<int64_t,uint64_t,double> {
using variant<int64_t,uint64_t,double>::variant;
constexpr var_t(unsigned u) : variant(uint64_t(u)) {}
};
int main()
{
var_t v1{1};
var_t v2{1ul};
var_t v3{1u}; // VALID
var_t v4{unsigned(1)}; // VALID
var_t v5{uint64_t(1)};
}
live example
No need to use cumbersome in_place_type. Sure it is useful but not this case.
Thanks everybody for attention

Convert C *FILE to C++ iostream with boost

I am fairly new to C++ and wanted to convert a *FILE (such as returned by popen()) to a iostream to be used with functions such as getline etc. I found the following code http://fw-geekycoder.blogspot.co.za/2011/06/how-to-convert-c-file-to-c-iostream.html, as well as similar code from a bunch of places, but the compiler moans about boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd); and boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd);
#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
void write() {
FILE* fp = fopen("whatever.txt", "w");
if (fp == NULL) {
perror("fopen error");
}
int fd = fileno(fp);
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd);
std::ostream os(&bis);
os << "Hello World!" << std::endl;
fclose(fp);
}
void read() {
FILE* fp = fopen("whatever.txt", "r");
if (fp == NULL) {
perror("fopen error");
}
int fd = fileno(fp);
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> bis(fd);
std::istream is(&bis);
while (is) {
std::string line;
std::getline(is, line);
std::cout << line << std::endl;
}
fclose(fp);
}
int main() {
write();
read();
return 0;
}
It seems like my system finds boost, but as if the API or something changed. What is the problem, here is my output from eclipse:
make all
Building file: ../src/boostPopenHandler.cpp
Invoking: GCC C++ Compiler
g++ -D__GXX_EXPERIMENTAL_CXX0X__ -I../../emdw/src -I../../patrecII/src -I../../ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -MMD -MP -MF"src/boostPopenHandler.d" -MT"src/boostPopenHandler.d" -o"src/boostPopenHandler.o" "../src/boostPopenHandler.cpp"
In file included from ../src/boostPopenHandler.cpp:4:0:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = char; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = char; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:13:83: required from here
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
{ open(detail::path(path), mode); }
^
In file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,
from ../src/boostPopenHandler.cpp:4:
/usr/include/boost/iostreams/detail/path.hpp:52:5: error: initializing argument 1 of ‘boost::iostreams::detail::path::path(const char*)’ [-fpermissive]
path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }
^
In file included from ../src/boostPopenHandler.cpp:4:0:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_source::file_descriptor_source(const Path&, std::ios_base::openmode) [with Path = char; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = char; T = boost::iostreams::file_descriptor_source; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::input_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:26:85: required from here
/usr/include/boost/iostreams/device/file_descriptor.hpp:194:36: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
{ open(detail::path(path), mode); }
^
In file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,
from ../src/boostPopenHandler.cpp:4:
/usr/include/boost/iostreams/detail/path.hpp:52:5: error: initializing argument 1 of ‘boost::iostreams::detail::path::path(const char*)’ [-fpermissive]
path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }
^
make: *** [src/boostPopenHandler.o] Error 1
Edit:Following the answer from Selçuk Cihan, I changed the relevant code to:
boost::iostreams::file_descriptor_source fds(fd);
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink>
...
boost::iostreams::file_descriptor_source fds(fd);
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source>
But I still get a list of compile errors:
**** Build of configuration Debug for project boostPopenHandler ****
make all
Building file: ../src/boostPopenHandler.cpp
Invoking: GCC C++ Compiler
g++ -I../../emdw/src -I../../patrecII/src -I../../ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -MMD -MP -MF"src/boostPopenHandler.d" -MT"src/boostPopenHandler.d" -o"src/boostPopenHandler.o" "../src/boostPopenHandler.cpp"
In file included from ../src/boostPopenHandler.cpp:4:0:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_source::file_descriptor_source(const Path&, std::ios_base::openmode) [with Path = int; std::ios_base::openmode = std::_Ios_Openmode]’:
../src/boostPopenHandler.cpp:13:52: required from here
/usr/include/boost/iostreams/device/file_descriptor.hpp:194:36: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
{ open(detail::path(path), mode); }
^
In file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,
from ../src/boostPopenHandler.cpp:4:
/usr/include/boost/iostreams/detail/path.hpp:52:5: error: initializing argument 1 of ‘boost::iostreams::detail::path::path(const char*)’ [-fpermissive]
path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }
^
In file included from ../src/boostPopenHandler.cpp:4:0:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: error: no matching function for call to ‘boost::iostreams::detail::path::path(const boost::iostreams::file_descriptor_source&)’
{ open(detail::path(path), mode); }
^
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: note: candidates are:
In file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,
from ../src/boostPopenHandler.cpp:4:
/usr/include/boost/iostreams/detail/path.hpp:138:5: note: boost::iostreams::detail::path::path(const wstring&)
path(const std::wstring&);
^
/usr/include/boost/iostreams/detail/path.hpp:138:5: note: no known conversion for argument 1 from ‘const boost::iostreams::file_descriptor_source’ to ‘const wstring& {aka const std::basic_string<wchar_t>&}’
/usr/include/boost/iostreams/detail/path.hpp:70:5: note: boost::iostreams::detail::path::path(const boost::iostreams::detail::path&)
path(const path& p)
^
/usr/include/boost/iostreams/detail/path.hpp:70:5: note: no known conversion for argument 1 from ‘const boost::iostreams::file_descriptor_source’ to ‘const boost::iostreams::detail::path&’
/usr/include/boost/iostreams/detail/path.hpp:64:14: note: template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::codecvt_type*)
explicit path(const Path& p, typename Path::codecvt_type* = 0)
^
/usr/include/boost/iostreams/detail/path.hpp:64:14: note: template argument deduction/substitution failed:
/usr/include/boost/iostreams/detail/path.hpp: In substitution of ‘template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::codecvt_type*) [with Path = boost::iostreams::file_descriptor_source]’:
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: required from ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/detail/path.hpp:64:14: error: no type named ‘codecvt_type’ in ‘class boost::iostreams::file_descriptor_source’
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/detail/path.hpp:57:14: note: template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::external_string_type*)
explicit path(const Path& p, typename Path::external_string_type* = 0)
^
/usr/include/boost/iostreams/detail/path.hpp:57:14: note: template argument deduction/substitution failed:
/usr/include/boost/iostreams/detail/path.hpp: In substitution of ‘template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::external_string_type*) [with Path = boost::iostreams::file_descriptor_source]’:
/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: required from ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/detail/path.hpp:57:14: error: no type named ‘external_string_type’ in ‘class boost::iostreams::file_descriptor_source’
/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of ‘boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5: required from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]’
../src/boostPopenHandler.cpp:14:84: required from here
/usr/include/boost/iostreams/detail/path.hpp:52:5: note: boost::iostreams::detail::path::path(const char*)
path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }
^
/usr/include/boost/iostreams/detail/path.hpp:52:5: note: no known conversion for argument 1 from ‘const boost::iostreams::file_descriptor_source’ to ‘const char*’
/usr/include/boost/iostreams/detail/path.hpp:49:5: note: boost::iostreams::detail::path::path(const string&)
path(const std::string& p) : narrow_(p), wide_(), is_wide_(false) { }
^
/usr/include/boost/iostreams/detail/path.hpp:49:5: note: no known conversion for argument 1 from ‘const boost::iostreams::file_descriptor_source’ to ‘const string& {aka const std::basic_string<char>&}’
/usr/include/boost/iostreams/detail/path.hpp:46:5: note: boost::iostreams::detail::path::path()
path() : narrow_(), wide_(), is_wide_(false) { }
^
/usr/include/boost/iostreams/detail/path.hpp:46:5: note: candidate expects 0 arguments, 1 provided
make: *** [src/boostPopenHandler.o] Error 1
Oh, you should be first declaring a file_descriptor_source as in
boost::iostreams::file_descriptor_source fds(fd);
and then comes your stream buffer
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> bis(fds);
Edit:
Sorry for the confusion, that ctor with an int parameter is deprecated and it seems that you do not have that ctor because otherwise your code would compile perfectly. That is why the above code i supplied needs a second mandatory parameter of either boost::iostreams::never_close_handle or boost::iostreams::close_handle
So it should read
boost::iostreams::file_descriptor_source fds(fd, boost::iostreams::close_handle);
otherwise you would still get that error. And same fix goes with the file_descriptor_sink also.
Now as for how you should read the errors:
/usr/include/boost/iostreams/device/file_descriptor.hpp: In
instantiation of
‘boost::iostreams::file_descriptor_source::file_descriptor_source(const
Path&, std::ios_base::openmode) [with Path = char;
std::ios_base::openmode = std::_Ios_Openmode]’:
Says that it tried to instantiate a file_descriptor_source with a template parameter choice of
[with Path = char; std::ios_base::openmode = std::_Ios_Openmode]
Since you only supplied an integer, the compiler tried to match that version of the ctor and failed to make the conversion.
You don't need Boost for this.
wanted to convert a *FILE (such as returned by popen()) to a iostream
Use pstreams instead (disclaimer, I wrote it, if that matters).
Some compilers provide extensions to create a streambuf from a C file without needing Boost, e.g. with GCC:
#include <ext/stdio_filebuf.h>
...
__gnu_cxx::stdio_filebuf<char> fb(fp, std::ios::out);
std::ostream os(&fb);