I would like to create a code that manage an array of boost::iostreams::filtering_stream
objects.
If the size of this array is known at compile time, I can use std::array
and this works without any problem:
#include <array>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
int main()
{
std::array<boost::iostreams::filtering_stream<boost::iostreams::input>, 3> m_inbufs;
m_inbufs[0].push(boost::iostreams::gzip_decompressor());
return 0;
}
Now the trouble comes when I substitute the array with a std::vector
. The following code does not compile:
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <vector>
int main()
{
std::vector<boost::iostreams::filtering_stream<boost::iostreams::input>> m_inbufs_vec;
m_inbufs_vec.emplace_back(boost::iostreams::filtering_stream<boost::iostreams::input>{});
return 0;
}
The error is rather long:
In file included from /usr/include/c++/13.2.1/x86_64-pc-linux-gnu/bits/c++allocator.h:33,
from /usr/include/c++/13.2.1/bits/allocator.h:46,
from /usr/include/c++/13.2.1/memory:65,
from /usr/include/boost/iostreams/filtering_stream.hpp:15,
from f_vec.cpp:1:
/usr/include/c++/13.2.1/bits/new_allocator.h: In instantiation of ‘void std::__new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = boost::iostreams::filtering_stream<boost::iostreams::input>; _Args = {boost::iostreams::filtering_stream<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>}; _Tp = boost::iostreams::filtering_stream<boost::iostreams::input>]’:
/usr/include/c++/13.2.1/bits/alloc_traits.h:537:17: required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(allocator_type&, _Up*, _Args&& ...) [with _Up = boost::iostreams::filtering_stream<boost::iostreams::input>; _Args = {boost::iostreams::filtering_stream<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>}; _Tp = boost::iostreams::filtering_stream<boost::iostreams::input>; allocator_type = std::allocator<boost::iostreams::filtering_stream<boost::iostreams::input> >]’
/usr/include/c++/13.2.1/bits/vector.tcc:117:30: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {boost::iostreams::filtering_stream<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>}; _Tp = boost::iostreams::filtering_stream<boost::iostreams::input>; _Alloc = std::allocator<boost::iostreams::filtering_stream<boost::iostreams::input> >; reference = boost::iostreams::filtering_stream<boost::iostreams::input>&]’
f_vec.cpp:8:28: required from here
/usr/include/c++/13.2.1/bits/new_allocator.h:187:11: error: use of deleted function ‘boost::iostreams::filtering_stream<boost::iostreams::input>::filtering_stream(const boost::iostreams::filtering_stream<boost::iostreams::input>&)’
187 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/filtering_stream.hpp:169:1: note: ‘boost::iostreams::filtering_stream<boost::iostreams::input>::filtering_stream(const boost::iostreams::filtering_stream<boost::iostreams::input>&)’ is implicitly deleted because the default definition would be ill-formed:
169 | BOOST_IOSTREAMS_DEFINE_FILTER_STREAM(filtering_stream, boost::iostreams::chain, char)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/filtering_stream.hpp:169:1: error: use of deleted function ‘boost::iostreams::detail::filtering_stream_base<boost::iostreams::chain<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char> >, boost::iostreams::public_>::filtering_stream_base(const boost::iostreams::detail::filtering_stream_base<boost::iostreams::chain<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char> >, boost::iostreams::public_>&)’
/usr/include/boost/iostreams/filtering_stream.hpp:72:7: note: ‘boost::iostreams::detail::filtering_stream_base<boost::iostreams::chain<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char> >, boost::iostreams::public_>::filtering_stream_base(const boost::iostreams::detail::filtering_stream_base<boost::iostreams::chain<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char> >, boost::iostreams::public_>&)’ is implicitly deleted because the default definition would be ill-formed:
72 | class filtering_stream_base
| ^~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/iostreams/filtering_stream.hpp:72:7: error: use of deleted function ‘std::basic_istream<_CharT, _Traits>::basic_istream(const std::basic_istream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’
In file included from /usr/include/boost/iostreams/detail/iostream.hpp:17,
from /usr/include/boost/iostreams/filtering_stream.hpp:18:
/usr/include/c++/13.2.1/istream:701:7: note: declared here
701 | basic_istream(const basic_istream&) = delete;
| ^~~~~~~~~~~~~
/usr/include/boost/iostreams/filtering_stream.hpp:72:7: error: use of deleted function ‘std::basic_ios<_CharT, _Traits>::basic_ios(const std::basic_ios<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’
72 | class filtering_stream_base
| ^~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/13.2.1/ios:46,
from /usr/include/c++/13.2.1/istream:40:
/usr/include/c++/13.2.1/bits/basic_ios.h:475:7: note: declared here
475 | basic_ios(const basic_ios&) = delete;
| ^~~~~~~~~
/usr/include/boost/iostreams/filtering_stream.hpp:169:1: error: use of deleted function ‘std::basic_ios<_CharT, _Traits>::basic_ios(const std::basic_ios<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’
169 | BOOST_IOSTREAMS_DEFINE_FILTER_STREAM(filtering_stream, boost::iostreams::chain, char)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/13.2.1/bits/basic_ios.h:475:7: note: declared here
475 | basic_ios(const basic_ios&) = delete;
| ^~~~~~~~~
In file included from /usr/include/c++/13.2.1/memory:69:
/usr/include/c++/13.2.1/bits/stl_uninitialized.h: In instantiation of ‘constexpr bool std::__check_constructible() [with _ValueType = boost::iostreams::filtering_stream<boost::iostreams::input>; _Tp = boost::iostreams::filtering_stream<boost::iostreams::input>&&]’:
/usr/include/c++/13.2.1/bits/stl_uninitialized.h:182:4: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = move_iterator<boost::iostreams::filtering_stream<boost::iostreams::input>*>; _ForwardIterator = boost::iostreams::filtering_stream<boost::iostreams::input>*]’
/usr/include/c++/13.2.1/bits/stl_uninitialized.h:373:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, allocator<_Tp>&) [with _InputIterator = move_iterator<boost::iostreams::filtering_stream<boost::iostreams::input>*>; _ForwardIterator = boost::iostreams::filtering_stream<boost::iostreams::input>*; _Tp = boost::iostreams::filtering_stream<boost::iostreams::input>]’
/usr/include/c++/13.2.1/bits/stl_uninitialized.h:399:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = boost::iostreams::filtering_stream<boost::iostreams::input>*; _ForwardIterator = boost::iostreams::filtering_stream<boost::iostreams::input>*; _Allocator = allocator<boost::iostreams::filtering_stream<boost::iostreams::input> >]’
/usr/include/c++/13.2.1/bits/vector.tcc:493:3: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(iterator, _Args&& ...) [with _Args = {boost::iostreams::filtering_stream<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>}; _Tp = boost::iostreams::filtering_stream<boost::iostreams::input>; _Alloc = std::allocator<boost::iostreams::filtering_stream<boost::iostreams::input> >; iterator = std::vector<boost::iostreams::filtering_stream<boost::iostreams::input> >::iterator]’
/usr/include/c++/13.2.1/bits/vector.tcc:123:21: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {boost::iostreams::filtering_stream<boost::iostreams::input, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>}; _Tp = boost::iostreams::filtering_stream<boost::iostreams::input>; _Alloc = std::allocator<boost::iostreams::filtering_stream<boost::iostreams::input> >; reference = boost::iostreams::filtering_stream<boost::iostreams::input>&]’
f_vec.cpp:8:28: required from here
/usr/include/c++/13.2.1/bits/stl_uninitialized.h:90:56: error: static assertion failed: result type must be constructible from input type
90 | static_assert(is_constructible<_ValueType, _Tp>::value,
| ^~~~~
/usr/include/c++/13.2.1/bits/stl_uninitialized.h:90:56: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
Basically, the problem is that emplace_back
tries to use the copy contructor, which is deleted here. Somehow I am not able to “directly” create a boost::iostreams::filtering_stream
as a vector element.
I have tried to use slightly different code, such as
m_inbufs_vec.resize(1);
but that gives the same error.
Given that declaring a single variable works, I found a workaround using unique_ptr
:
#include <memory>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <vector>
int main()
{
std::vector<std::unique_ptr<boost::iostreams::filtering_stream<boost::iostreams::input>>> m_inbufs_vec;
m_inbufs_vec.emplace_back(std::make_unique<boost::iostreams::filtering_stream<boost::iostreams::input>>());
return 0;
}
This circumvents the problem, but it is rather cumbersome.
Is there a way to tell the compile to create a boost::iostreams::filtering_stream
directly as the next element of a std::vector
?
1