Convert C *FILE to C++ iostream with boost - c++

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);

Related

Boost.Iostreams stream can't forward 4 constructor arguments

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>

Why doesn't C++ variadic template accept iostream value as a parameter?

I refer this link to implement variadic template:
#include <iostream>
#include <sstream>
// base case
void doPrint(std::ostream &out) {}
template <typename T, typename... Args>
void doPrint(std::ostream &out, T t, Args... args)
{
out << t; // add comma here, see below
doPrint(out, args...);
}
int main() {
// See how it works even better than varargs?
doPrint(std::cout, "Hola", " mundo ");
return 0;
}
But if I change function parameter from reference
void doPrint(std::ostream &out)
......
template <typename T, typename... Args>
void doPrint(std::ostream &out, T t, Args... args)
to value:
void doPrint(std::ostream out)
......
template <typename T, typename... Args>
void doPrint(std::ostream out, T t, Args... args)
I get the following build errors:
test.cpp: In function 'int main()':
test.cpp:16:40: error: 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]' is protected within this context
doPrint(std::cout, "Hola", " mundo ");
^
In file included from /usr/include/c++/7.1.1/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7.1.1/ostream:391:7: note: declared protected here
basic_ostream(const basic_ostream&) = delete;
^~~~~~~~~~~~~
test.cpp:16:40: error: use of deleted function 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]'
doPrint(std::cout, "Hola", " mundo ");
^
In file included from /usr/include/c++/7.1.1/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7.1.1/ostream:391:7: note: declared here
basic_ostream(const basic_ostream&) = delete;
^~~~~~~~~~~~~
test.cpp:8:6: note: initializing argument 1 of 'void doPrint(std::ostream, T, Args ...) [with T = const char*; Args = {const char*}; std::ostream = std::basic_ostream<char>]'
void doPrint(std::ostream out, T t, Args... args)
^~~~~~~
test.cpp: In instantiation of 'void doPrint(std::ostream, T, Args ...) [with T = const char*; Args = {const char*}; std::ostream = std::basic_ostream<char>]':
test.cpp:16:40: required from here
test.cpp:11:12: error: 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]' is protected within this context
doPrint(out, args...);
~~~~~~~^~~~~~~~~~~~~~
In file included from /usr/include/c++/7.1.1/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7.1.1/ostream:391:7: note: declared protected here
basic_ostream(const basic_ostream&) = delete;
^~~~~~~~~~~~~
test.cpp:11:12: error: use of deleted function 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]'
doPrint(out, args...);
~~~~~~~^~~~~~~~~~~~~~
In file included from /usr/include/c++/7.1.1/iostream:39:0,
from test.cpp:1:
/usr/include/c++/7.1.1/ostream:391:7: note: declared here
basic_ostream(const basic_ostream&) = delete;
^~~~~~~~~~~~~
test.cpp:8:6: note: initializing argument 1 of 'void doPrint(std::ostream, T, Args ...) [with T = const char*; Args = {}; std::ostream = std::basic_ostream<char>]'
void doPrint(std::ostream out, T t, Args... args)
^~~~~~~
Per my understanding, use value may not have a good performance as reference, but it shouldn't cause compilation error. Why doesn't C++ variadic template accept iostream value as a parameter?
It's simply, because copy constructor in std::basic_ostream is deleted (by standard)
read about this here at cppreference.
So std::cout you can move or take by reference
example:
class A {
public:
A(const A& a) = delete;
};
void foo1(const A& a)
{
std::cout << "HEY1" << std::endl;
}
void foo2(const A a)
{
std::cout << "HEY2" << std::endl;
}
int main() {
A a{};
foo1(a);
// foo2(a);
return 0;
}
So in example you see that first function work fine when copy constructor is deleted, but if you uncomment foo2(a), that you get some information from compile e.g. (VS)
'A::A(const A &)': attempting to reference a deleted function
The explanation is in the first couple of lines of error messages.
std::ostream is actually a typedef for std::basic_ostream<char, std::char_traits<char> >.
Passing a std::ostream by value calls the copy constructor of the object, and the std::basic_ostream template has explicitly deleted the copy constructor so it cannot be called.

"'boost::bind' is ambiguous" C++ error

I'm trying to control an arduino from a c++ program, after some research I found this, but the problem is, it does not compile on eclipse.
It gives me 2 errors at line 102 in 3_async>AsyncSerial.cpp
boost::thread t(boost::bind(&asio::io_service::run, &pimpl->io));
Screenshot
If compiled by using its own CMakeLists.txt it gives no errors.
Any way to know what settings am I missing on eclipse if there are any?
EDIT:
as suggested I'm posting the logs:
12:32:18 **** Incremental Build of configuration Debug for project Arduino_SerialTest ****
make all
Building file: ../src/lib/pica_protocol/Receiver.cpp
Invoking: Cross G++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"src/lib/pica_protocol/Receiver.d" -MT"src/lib/pica_protocol/Receiver.o" -o "src/lib/pica_protocol/Receiver.o" "../src/lib/pica_protocol/Receiver.cpp"
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
from /usr/include/boost/thread/thread.hpp:12,
from /usr/include/boost/thread.hpp:13,
from ../src/lib/pica_protocol/../serial/AsyncSerial.h:14,
from ../src/lib/pica_protocol/../serial/BufferedAsyncSerial.h:8,
from ../src/lib/pica_protocol/Receiver.h:12,
from ../src/lib/pica_protocol/Receiver.cpp:8:
/usr/include/boost/thread/detail/thread.hpp: In instantiation of ‘void boost::detail::thread_data<F>::run() [with F = void (pica_protocol::Receiver::*)()]’:
../src/lib/pica_protocol/Receiver.cpp:75:1: required from here
/usr/include/boost/thread/detail/thread.hpp:117:17: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘((boost::detail::thread_data<void (pica_protocol::Receiver::*)()>*)this)->boost::detail::thread_data<void (pica_protocol::Receiver::*)()>::f (...)’, e.g. ‘(... ->* ((boost::detail::thread_data<void (pica_protocol::Receiver::*)()>*)this)->boost::detail::thread_data<void (pica_protocol::Receiver::*)()>::f) (...)’
f();
^
In file included from /usr/include/boost/bind.hpp:22:0,
from ../src/lib/pica_protocol/../serial/AsyncSerial.h:13,
from ../src/lib/pica_protocol/../serial/BufferedAsyncSerial.h:8,
from ../src/lib/pica_protocol/Receiver.h:12,
from ../src/lib/pica_protocol/Receiver.cpp:8:
/usr/include/boost/bind/bind.hpp: In instantiation of ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf1<void, pica_protocol::Receiver, std::basic_string<char> >; A = boost::_bi::list0; A1 = boost::_bi::value<pica_protocol::Receiver*>; A2 = boost::_bi::value<std::basic_string<char>*>]’:
/usr/include/boost/bind/bind_template.hpp:20:59: required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void; F = boost::_mfi::mf1<void, pica_protocol::Receiver, std::basic_string<char> >; L = boost::_bi::list2<boost::_bi::value<pica_protocol::Receiver*>, boost::_bi::value<std::basic_string<char>*> >; boost::_bi::bind_t<R, F, L>::result_type = void]’
/usr/include/boost/thread/detail/thread.hpp:117:17: required from ‘void boost::detail::thread_data<F>::run() [with F = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pica_protocol::Receiver, std::basic_string<char> >, boost::_bi::list2<boost::_bi::value<pica_protocol::Receiver*>, boost::_bi::value<std::basic_string<char>*> > >]’
../src/lib/pica_protocol/Receiver.cpp:75:1: required from here
/usr/include/boost/bind/bind.hpp:313:34: error: no match for call to ‘(boost::_mfi::mf1<void, pica_protocol::Receiver, std::basic_string<char> >) (pica_protocol::Receiver*&, std::basic_string<char>*&)’
unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
^
In file included from /usr/include/boost/mem_fn.hpp:22:0,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from ../src/lib/pica_protocol/../serial/AsyncSerial.h:13,
from ../src/lib/pica_protocol/../serial/BufferedAsyncSerial.h:8,
from ../src/lib/pica_protocol/Receiver.h:12,
from ../src/lib/pica_protocol/Receiver.cpp:8:
/usr/include/boost/bind/mem_fn_template.hpp:136:65: note: candidates are:
template<class R, class T, class A1 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf1)
^
In file included from /usr/include/boost/bind/mem_fn.hpp:215:0,
from /usr/include/boost/mem_fn.hpp:22,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from ../src/lib/pica_protocol/../serial/AsyncSerial.h:13,
from ../src/lib/pica_protocol/../serial/BufferedAsyncSerial.h:8,
from ../src/lib/pica_protocol/Receiver.h:12,
from ../src/lib/pica_protocol/Receiver.cpp:8:
/usr/include/boost/bind/mem_fn_template.hpp:163:7: note: R boost::_mfi::mf1<R, T, A1>::operator()(T*, A1) const [with R = void; T = pica_protocol::Receiver; A1 = std::basic_string<char>]
R operator()(T * p, A1 a1) const
^
/usr/include/boost/bind/mem_fn_template.hpp:163:7: note: no known conversion for argument 2 from ‘std::basic_string<char>*’ to ‘std::basic_string<char>’
/usr/include/boost/bind/mem_fn_template.hpp:168:25: note: template<class U> R boost::_mfi::mf1<R, T, A1>::operator()(U&, A1) const [with U = U; R = void; T = pica_protocol::Receiver; A1 = std::basic_string<char>]
template<class U> R operator()(U & u, A1 a1) const
^
/usr/include/boost/bind/mem_fn_template.hpp:168:25: note: template argument deduction/substitution failed:
In file included from /usr/include/boost/bind.hpp:22:0,
from ../src/lib/pica_protocol/../serial/AsyncSerial.h:13,
from ../src/lib/pica_protocol/../serial/BufferedAsyncSerial.h:8,
from ../src/lib/pica_protocol/Receiver.h:12,
from ../src/lib/pica_protocol/Receiver.cpp:8:
/usr/include/boost/bind/bind.hpp:313:34: note: cannot convert ‘(& a)->boost::_bi::list0::operator[]<std::basic_string<char>*>((* &((boost::_bi::list2<boost::_bi::value<pica_protocol::Receiver*>, boost::_bi::value<std::basic_string<char>*> >*)this)->boost::_bi::list2<boost::_bi::value<pica_protocol::Receiver*>, boost::_bi::value<std::basic_string<char>*> >::<anonymous>.boost::_bi::storage2<boost::_bi::value<pica_protocol::Receiver*>, boost::_bi::value<std::basic_string<char>*> >::a2_))’ (type ‘std::basic_string<char>*’) to type ‘std::basic_string<char>’
unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
^
In file included from /usr/include/boost/bind/mem_fn.hpp:215:0,
from /usr/include/boost/mem_fn.hpp:22,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from ../src/lib/pica_protocol/../serial/AsyncSerial.h:13,
from ../src/lib/pica_protocol/../serial/BufferedAsyncSerial.h:8,
from ../src/lib/pica_protocol/Receiver.h:12,
from ../src/lib/pica_protocol/Receiver.cpp:8:
/usr/include/boost/bind/mem_fn_template.hpp:176:25: note: template<class U> R boost::_mfi::mf1<R, T, A1>::operator()(const U&, A1) const [with U = U; R = void; T = pica_protocol::Receiver; A1 = std::basic_string<char>]
template<class U> R operator()(U const & u, A1 a1) const
^
/usr/include/boost/bind/mem_fn_template.hpp:176:25: note: template argument deduction/substitution failed:
In file included from /usr/include/boost/bind.hpp:22:0,
from ../src/lib/pica_protocol/../serial/AsyncSerial.h:13,
from ../src/lib/pica_protocol/../serial/BufferedAsyncSerial.h:8,
from ../src/lib/pica_protocol/Receiver.h:12,
from ../src/lib/pica_protocol/Receiver.cpp:8:
/usr/include/boost/bind/bind.hpp:313:34: note: cannot convert ‘(& a)->boost::_bi::list0::operator[]<std::basic_string<char>*>((* &((boost::_bi::list2<boost::_bi::value<pica_protocol::Receiver*>, boost::_bi::value<std::basic_string<char>*> >*)this)->boost::_bi::list2<boost::_bi::value<pica_protocol::Receiver*>, boost::_bi::value<std::basic_string<char>*> >::<anonymous>.boost::_bi::storage2<boost::_bi::value<pica_protocol::Receiver*>, boost::_bi::value<std::basic_string<char>*> >::a2_))’ (type ‘std::basic_string<char>*’) to type ‘std::basic_string<char>’
unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
^
In file included from /usr/include/boost/bind/mem_fn.hpp:215:0,
from /usr/include/boost/mem_fn.hpp:22,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from ../src/lib/pica_protocol/../serial/AsyncSerial.h:13,
from ../src/lib/pica_protocol/../serial/BufferedAsyncSerial.h:8,
from ../src/lib/pica_protocol/Receiver.h:12,
from ../src/lib/pica_protocol/Receiver.cpp:8:
/usr/include/boost/bind/mem_fn_template.hpp:184:7: note: R boost::_mfi::mf1<R, T, A1>::operator()(T&, A1) const [with R = void; T = pica_protocol::Receiver; A1 = std::basic_string<char>]
R operator()(T & t, A1 a1) const
^
/usr/include/boost/bind/mem_fn_template.hpp:184:7: note: no known conversion for argument 1 from ‘pica_protocol::Receiver*’ to ‘pica_protocol::Receiver&’
make: *** [src/lib/pica_protocol/Receiver.o] Errore 1
12:32:20 Build Finished (took 2s.670ms)
EDIT 2:
ok I fixed the ambiguity error by casting the io_service::run like that:
boost::thread t(boost::bind(static_cast<std::size_t(asio::io_service::*)(void)>(&asio::io_service::run), &pimpl->io));
but the compiler error remains, hope someone knows how to fix that ...

Where is piecewise_construct for boost::container::map::emplace()?

Using Boost, I am trying to emplace() a key/value pair into a boost::container::map. The value needs multiple arguments for the constructor. From what I've been able to find, I need to use piecewise_construct and pass the constructor args in tuples. This works with std::map<K,V>, but I can't get it to work using boost::container::map<K,V> The closest Boost doc I can find shows boost::unordered_multimap<K,V>, but not a plain map<K,V>.
#include <map>
#include <boost/tuple/tuple.hpp>
#include <boost/container/map.hpp>
#include <boost/unordered_set.hpp>
class A {
public:
/**/ A( int ) { }
bool operator<( const A & ) const { return false; }
} ;
class B {
public:
/**/ B( int, const char * ) { }
} ;
int
main( int, char ** )
{
A a( 100 );
B b( 200, "foo" );
std::map<A,B> mgood;
mgood.emplace( std::piecewise_construct,
std::make_tuple( 100 ),
std::make_tuple( 200, "Hello" ) );
#if 1
boost::container::map<A,B> mbad;
mbad.emplace( boost::unordered::piecewise_construct,
boost::make_tuple( 300 ),
boost::make_tuple( 400, "World" ) );
#endif
}
The g++-4.9.2 error messages are impenetrable (to me, anyway):
make -k tst g++ -DBOOST_LOG_DYN_LINK -g -std=c++11 -c -o tst.o
tst.cc In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp: In
instantiation of âstatic void
boost::container::allocator_traits::priv_construct(boost::move_detail::false_type,
Allocator&, T*, Args&& ...) [with T =
boost::container::container_detail::pair; Args = {const
boost::unordered::piecewise_construct_t&, boost::tuples::tuple, boost::tuples::tuple}; Allocator =
boost::container::new_allocator, void*, (boost::container::tree_type_enum)0u, true> >;
boost::move_detail::false_type =
boost::move_detail::integral_constant]â:
/usr/local/include/boost/container/allocator_traits.hpp:353:86:
required from âstatic void
boost::container::allocator_traits::construct(Allocator&,
T*, Args&& ...) [with T = boost::container::container_detail::pair; Args = {const boost::unordered::piecewise_construct_t&,
boost::tuples::tuple,
boost::tuples::tuple}; Allocator =
boost::container::new_allocator, void*, (boost::container::tree_type_enum)0u, true> >]â
/usr/local/include/boost/container/detail/node_alloc_holder.hpp:167:81:
required from
âboost::container::container_detail::node_alloc_holder::NodePtr
boost::container::container_detail::node_alloc_holder::create_node(Args&& ...) [with Args = {const
boost::unordered::piecewise_construct_t&, boost::tuples::tuple, boost::tuples::tuple}; Allocator =
boost::container::new_allocator >; ICont =
boost::intrusive::rbtree_impl, void*, (boost::container::tree_type_enum)0u, true>,
boost::intrusive::rbtree_node_traits,
(boost::intrusive::link_mode_type)0u, boost::intrusive::dft_tag, 3u>,
void,
boost::container::value_to_node_compare, void*, (boost::container::tree_type_enum)0u, true>,
boost::intrusive::tree_value_compare,
std::less,
boost::container::container_detail::select1st >
, long unsigned int, true, void>; boost::container::container_detail::node_alloc_holder::NodePtr =
boost::container::container_detail::tree_node,
void*, (boost::container::tree_type_enum)0u, true>]â
/usr/local/include/boost/container/detail/tree.hpp:922:94: required
from
âstd::pair,
Options:: tree_type, Options:: optimize_size>::type::iterator, false>,
bool> boost::container::container_detail::tree::emplace_unique(Args&& ...) [with Args =
{const boost::unordered::piecewise_construct_t&,
boost::tuples::tuple,
boost::tuples::tuple}; Key = A; T = std::pair;
KeyOfValue =
boost::container::container_detail::select1st >;
Compare = std::less; Allocator =
boost::container::new_allocator >; Options =
boost::container::tree_opt<(boost::container::tree_type_enum)0u,
true>; typename
boost::container::container_detail::intrusive_tree_type,
Options:: tree_type, Options:: optimize_size>::type::iterator =
boost::intrusive::tree_iterator, void*, (boost::container::tree_type_enum)0u, true>,
boost::intrusive::rbtree_node_traits,
(boost::intrusive::link_mode_type)0u, boost::intrusive::dft_tag, 3u>,
false>]â /usr/local/include/boost/container/map.hpp:665:72:
required from âstd::pair, boost::container::container_detail::select1st >, Compare, Allocator, MapOptions>::iterator, bool> boost::container::map::emplace(Args&& ...) [with Args = {const
boost::unordered::piecewise_construct_t&, boost::tuples::tuple, boost::tuples::tuple}; Key = A; T = B;
Compare = std::less; Allocator =
boost::container::new_allocator >; MapOptions =
boost::container::tree_opt<(boost::container::tree_type_enum)0u,
true>; typename boost::container::container_detail::tree,
boost::container::container_detail::select1st >, Compare, Allocator, MapOptions>::iterator = boost::container::container_detail::iterator_from_iiterator, void*, (boost::container::tree_type_enum)0u, true>,
boost::intrusive::rbtree_node_traits,
(boost::intrusive::link_mode_type)0u, boost::intrusive::dft_tag, 3u>,
false>, false>]â tst.cc:90:53: required from here
/usr/local/include/boost/container/allocator_traits.hpp:408:10: error:
no matching function for call to
âboost::container::container_detail::pair::pair(const
boost::unordered::piecewise_construct_t&, boost::tuples::tuple, boost::tuples::tuple)â
{ ::new((void)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
candidates are: In file included from
/usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:146:4: note:
template
boost::container::container_detail::pair::pair(std::pair<_U1,
_U2>&&)
pair(BOOST_RV_REF_BEG std::pair BOOST_RV_REF_END p)
^ /usr/local/include/boost/container/detail/pair.hpp:146:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
types âstd::pair<_T1, _T2>â and âconst
boost::unordered::piecewise_construct_tâ have incompatible
cv-qualifiers
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:141:4: note:
boost::container::container_detail::pair::pair(std::pair<_T1,
_T2>&&) [with T1 = A; T2 = B]
pair(BOOST_RV_REF_BEG std::pair BOOST_RV_REF_END p)
^ /usr/local/include/boost/container/detail/pair.hpp:141:4: note: candidate expects 1 argument, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:137:4: note:
template
boost::container::container_detail::pair::pair(const
std::pair<_U1, _U2>&)
pair(const std::pair& p)
^ /usr/local/include/boost/container/detail/pair.hpp:137:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
âconst boost::unordered::piecewise_construct_tâ is not derived
from âconst std::pair<_T1, _T2>â
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:132:4: note:
boost::container::container_detail::pair::pair(const
std::pair<_T1, _T2>&) [with T1 = A; T2 = B]
pair(const std::pair& x)
^ /usr/local/include/boost/container/detail/pair.hpp:132:4: note: candidate expects 1 argument, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:126:4: note:
template
boost::container::container_detail::pair::pair(U&&, V&&)
pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
^ /usr/local/include/boost/container/detail/pair.hpp:126:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
candidate expects 2 arguments, 3 provided
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:120:4: note:
boost::container::container_detail::pair::pair(const T1&,
const T2&) [with T1 = A; T2 = B]
pair(const T1 &t1, const T2 &t2)
^ /usr/local/include/boost/container/detail/pair.hpp:120:4: note: candidate expects 2 arguments, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:115:4: note:
template
boost::container::container_detail::pair::pair(boost::container::container_detail::pair&&)
pair(BOOST_RV_REF_BEG pair BOOST_RV_REF_END p)
^ /usr/local/include/boost/container/detail/pair.hpp:115:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
types âboost::container::container_detail::pairâ and
âconst boost::unordered::piecewise_construct_tâ have incompatible
cv-qualifiers
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:110:4: note:
template
boost::container::container_detail::pair::pair(const
boost::container::container_detail::pair&)
pair(const pair &p)
^ /usr/local/include/boost/container/detail/pair.hpp:110:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
âconst boost::unordered::piecewise_construct_tâ is not derived
from âconst boost::container::container_detail::pairâ
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:105:4: note:
boost::container::container_detail::pair::pair(boost::container::container_detail::pair&&) [with T1
= A; T2 = B]
pair(BOOST_RV_REF(pair) p)
^ /usr/local/include/boost/container/detail/pair.hpp:105:4: note: candidate expects 1 argument, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:100:4: note:
boost::container::container_detail::pair::pair(const
boost::container::container_detail::pair&) [with T1 = A; T2 =
B]
pair(const pair& x)
^ /usr/local/include/boost/container/detail/pair.hpp:100:4: note: candidate expects 1 argument, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:95:4: note:
boost::container::container_detail::pair::pair() [with T1 = A;
T2 = B]
pair()
^ /usr/local/include/boost/container/detail/pair.hpp:95:4: note: candidate expects 0 arguments, 3 provided : recipe for target
'tst.o' failed make: *** [tst.o] Error 1 make: Target 'tst' not remade
because of errors.
Compilation exited abnormally with code 2 at Sat Apr 2 17:11:28
Can you point me in a useful direction? (I'd prefer not to mix boost and std containers; it should be possible to emplace into a boost::container::map, right?)
It appears that piecewise_construct is not implemented for boost::pair (which is the type for boost::container::map entries). See .../boost/container/detail/pair.hpp:151:
//piecewise_construct missing
//template <class U, class V> pair(pair<U, V>&& p);
//template <class... Args1, class... Args2>
// pair(piecewise_construct_t, tuple<Args1...> first_args,
// tuple<Args2...> second_args);
I guess the implementation for this is tough.
piecewise_construct support for both C++03 and C++11 capable compilers was added in commit:
https://github.com/boostorg/container/commit/79a75f470e75f35f5f2a91e10fcc67d03b0a2160
and will be officially released in Boost 1.62. The following code compiles fine:
#include <boost/tuple/tuple.hpp>
#include <tuple>
#include <boost/container/map.hpp>
class A {
public:
/**/ A( int ) { }
bool operator<( const A & ) const { return false; }
} ;
class B {
public:
/**/ B( int, const char * ) { }
} ;
int main( int, char *[] )
{
A a( 100 );
B b( 200, "foo" );
boost::container::map<A,B> m;
//1) Both Boost.Tuple and std tuple supported
//2) std:: or boost::container::piecewise_construct supported
m.emplace( boost::container::piecewise_construct,
boost::make_tuple( 300 ),
boost::make_tuple( 400, "World" ) );
m.emplace( std::piecewise_construct,
std::make_tuple( 400 ),
std::make_tuple( 500, "World2" ) );
}

Templated move ctor for wrapped unique_ptr

I want something that's like unique_ptr, but guaranteed (within reason) to be non-null. I wrote this class that contains a unique_ptr, and I wrote this move constructor that I'd hoped would allow me to move-construct one of my pointers from another, as long as the underlying unique_ptr could be similarly move-constructed. So, I first try it with something simple; move-constructing a pointer-to-int from a pointer-to-int.
#include <memory>
#include <utility>
#include <cassert>
template<
typename T
>
class Nonup
{
private:
std::unique_ptr<T> m_ptr;
public:
explicit Nonup( T* p )
: m_ptr( p )
{ assert( p ); }
Nonup( const Nonup& ) = delete;
Nonup& operator=( const Nonup& ) = delete;
template<typename U>
Nonup( Nonup<U>&& old )
:
m_ptr( std::move( old ) )
{}
Nonup& operator=( Nonup&& rhs ) = default;
decltype( *m_ptr ) operator*() const { return *m_ptr; }
};
int main()
{
Nonup<int> first( new int( 42 ) );
Nonup<int> second( std::move( first ) );
return 0;
}
Why does g++ 4.7.0 give errors on the move-construction of the variable second? The output of "g++ -std=c++11 main.cpp" follows.
main.cpp: In instantiation of ‘Nonup<T>::Nonup(Nonup<U>&&) [with U = int; T = int]’:
main.cpp:40:43: required from here
main.cpp:27:37: error: no matching function for call to ‘std::unique_ptr<int, std::default_delete<int> >::unique_ptr(std::remove_reference<Nonup<int>&>::type)’
main.cpp:27:37: note: candidates are:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:164:2: note: template<class _Up, class> std::unique_ptr::unique_ptr(std::auto_ptr<_Up>&&)
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:164:2: note: template argument deduction/substitution failed:
main.cpp:27:37: note: ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ is not derived from ‘std::auto_ptr<_Up>’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:155:2: note: template<class _Up, class _Ep, class> std::unique_ptr::unique_ptr(std::unique_ptr<_Up, _Ep>&&)
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:155:2: note: template argument deduction/substitution failed:
main.cpp:27:37: note: ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ is not derived from ‘std::unique_ptr<_Up, _Ep>’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:142:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int; _Dp = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:142:7: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::unique_ptr<int, std::default_delete<int> >&&’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:136:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with _Tp = int; _Dp = std::default_delete<int>; std::nullptr_t = std::nullptr_t]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:136:17: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::nullptr_t’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:130:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::remove_reference<_To>::type&&) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*; typename std::remove_reference<_To>::type = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:130:7: note: candidate expects 2 arguments, 1 provided
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:125:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*; typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type = const std::default_delete<int>&]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:125:7: note: candidate expects 2 arguments, 1 provided
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:120:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:120:7: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::unique_ptr<int, std::default_delete<int> >::pointer {aka int*}’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:114:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int; _Dp = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:114:17: note: candidate expects 0 arguments, 1 provided
Thanks!
You're trying to initialise m_ptr from the other Nonup, rather than its m_ptr. The move constructor's initialiser should be:
m_ptr( std::move( old.m_ptr ) )
^^^^^^