Read file and split and trim each line with cpp20 - c++

I have created a code that fits my specific need - to split the string (read from a file) at comma stripping any whitespaces. also, I want to convert these substrings to double and store them in std::vector.
I use ranges library in c++20 and implement like bellow:
#include <iostream>
#include <fstream>
#include <ranges>
#include <algorithm>
#include <vector>
auto join_character_in_each_subranges = [](auto &&rng) { return std::string_view(&*rng.begin(), std::ranges::distance(rng)); };
auto trimming = std::ranges::views::filter([](auto character){ return !std::isspace(character);});
typedef std::vector<double> LineList;
typedef std::vector<LineList> List;
int main () {
std::ifstream myfile;
std::string myline;
List list;
myfile.open("data.txt");
while (std::getline(myfile, myline))
{
LineList line_list;
for (auto words : myline
| std::ranges::views::split(',')
| std::ranges::views::transform(join_character_in_each_subranges))
{
auto words_trimming = words | trimming;
std::string clean_numbers;
std::ranges::for_each(words_trimming, [&](auto character){ clean_numbers += character;});
line_list.push_back(atof(clean_numbers.c_str()));
}
list.push_back(line_list);
}
}
First, iterate on myline sentences and splits the view into subranges on the delimiter
myline | std::ranges::views::split(',')
append each character inside subranges and view into the std::string with transform function
std::transform applies the given function to a range and stores the result in another range.
std::ranges::views::transform(join_character_in_each_subranges)
also, remove any prefix and suffix from view ranges
auto words_trimming = words | trimming;
and convert view ranges to std::string with
std::ranges::for_each(words_trimming, [&](auto character){ clean_number += character;});
finally, convert each clean_number to double and push_back into the list.
line_list.push_back(atof(clean_words.c_str()));
but when I change this code to
for (auto words : myline
| std::ranges::views::split(',')
| std::ranges::views::transform(join_character_in_each_subranges)
| trimming)
I've got a lot of errors.
read.cpp:26:17: error: no match for 'operator|' (operand types are 'std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, <lambda(auto:16&&)> >' and 'std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{<lambda(auto:17&&)>}>::<lambda(_Range&&)> >')
23 | for (auto words : myline
| ~~~~~~
24 | | std::ranges::views::split(',')
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 | | std::ranges::views::transform(join_character_in_each_subranges)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, <lambda(auto:16&&)> >
26 | | trimming)
| ^ ~~~~~~~~
| |
| std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{<lambda(auto:17&&)>}>::<lambda(_Range&&)> >
In file included from read.cpp:3:
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ranges:1183:4: note: candidate: 'template<class _Tp> constexpr auto std::ranges::views::__adaptor::operator|(const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>&, const std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{<lambda(auto:17&&)>}>::<lambda(_Range&&)> >&)'
1183 | operator|(const _RangeAdaptorClosure<_Tp>& __x,
| ^~~~~~~~
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ranges:1183:4: note: template argument deduction/substitution failed:
read.cpp:26:19: note: 'std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, <lambda(auto:16&&)> >' is not derived from 'const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>'
26 | | trimming)
| ^~~~~~~~
In file included from read.cpp:3:
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ranges:1178:4: note: candidate: 'constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>&) [with _Range = std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, <lambda(auto:16&&)> >; _Callable = std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{<lambda(auto:17&&)>}>::<lambda(_Range&&)>]'
1178 | operator|(_Range&& __r, const _RangeAdaptorClosure& __o)
| ^~~~~~~~
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ranges:1178:4: note: constraints not satisfied
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ranges: In instantiation of 'constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>&) [with _Range = std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, <lambda(auto:16&&)> >; _Callable = std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{<lambda(auto:17&&)>}>::<lambda(_Range&&)>]':
read.cpp:26:19: required from here
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ranges:1178:4: required by the constraints of 'template<class _Callable> template<class _Range> requires (viewable_range<_Range>) && requires{(declval<_Callable>)()((declval<_Range>)());} constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>&)'
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ranges:1176:13: in requirements [with _Range = std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::ranges::single_view<char> >, ._anon_104>; _Callable = std::ranges::views::__adaptor::_RangeAdaptor<std::ranges::views::._anon_83>::operator()::._anon_106]
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ranges:1176:44: note: the required expression 'declval<_Callable>()(declval<_Range>())' is invalid
1176 | requires requires { declval<_Callable>()(declval<_Range>()); }
| ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
In file included from /usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ios:42,
from /usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/ostream:38,
from /usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/iostream:39,
from read.cpp:1:
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/bits/ios_base.h:87:3: note: candidate: 'constexpr std::_Ios_Fmtflags std::operator|(std::_Ios_Fmtflags, std::_Ios_Fmtflags)'
87 | operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
| ^~~~~~~~
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/bits/ios_base.h:87:27: note: no known conversion for argument 1 from 'std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, <lambda(auto:16&&)> >' to 'std::_Ios_Fmtflags'
87 | operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
| ~~~~~~~~~~~~~~^~~
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/bits/ios_base.h:129:3: note: candidate: 'constexpr std::_Ios_Openmode std::operator|(std::_Ios_Openmode, std::_Ios_Openmode)'
129 | operator|(_Ios_Openmode __a, _Ios_Openmode __b)
| ^~~~~~~~
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/bits/ios_base.h:129:27: note: no known conversion for argument 1 from 'std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, <lambda(auto:16&&)> >' to 'std::_Ios_Openmode'
129 | operator|(_Ios_Openmode __a, _Ios_Openmode __b)
| ~~~~~~~~~~~~~~^~~
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/bits/ios_base.h:169:3: note: candidate: 'constexpr std::_Ios_Iostate std::operator|(std::_Ios_Iostate, std::_Ios_Iostate)'
169 | operator|(_Ios_Iostate __a, _Ios_Iostate __b)
| ^~~~~~~~
/usr/local/Cellar/gcc#10/10.3.0/include/c++/10.3.0/bits/ios_base.h:169:26: note: no known conversion for argument 1 from 'std::ranges::transform_view<std::ranges::split_view<std::ranges::ref_view<std::__cxx11::basic_string<char> >, std::ranges::single_view<char> >, <lambda(auto:16&&)> >' to 'std::_Ios_Iostate'
169 | operator|(_Ios_Iostate __a, _Ios_Iostate __b)
| ~~~~~~~~~~~~~^~~
how fix this problem?
Thanks

According to Frank's comment change trimming like this:
auto trimming = std::ranges::views::transform(std::ranges::views::filter([](char character){return !std::isspace(character); }));

Related

Is there a way around obtaining the address of a const object

I am trying to achieve the following
#include<iostream>
#include <vector>
class var {
public:
static std::vector<var*> variables_;
friend var operator-(const var& v) {
// this is not compiling
variables_.push_back(&v);
}
};
int main() { var x; }
The error
est.cpp: In function ‘var operator-(const var&)’:
test.cpp:10:32: error: no matching function for call to ‘push_back(const var*)’
10 | variables_.push_back(&v);
| ^
In file included from /usr/include/c++/10/vector:67,
from test.cpp:2:
/usr/include/c++/10/bits/stl_vector.h:1187:7: note: candidate: ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = var*; _Alloc = std::allocator<var*>; std::vector<_Tp, _Alloc>::value_type = var*]’ (near match)
1187 | push_back(const value_type& __x)
| ^~~~~~~~~
/usr/include/c++/10/bits/stl_vector.h:1187:7: note: conversion of argument 1 would be ill-formed:
test.cpp:10:30: error: invalid conversion from ‘const var*’ to ‘std::vector<var*>::value_type’ {aka ‘var*’} [-fpermissive]
10 | variables_.push_back(&v);
| ^~
| |
| const var*
In file included from /usr/include/c++/10/vector:67,
from test.cpp:2:
/usr/include/c++/10/bits/stl_vector.h:1203:7: note: candidate: ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = var*; _Alloc = std::allocator<var*>; std::vector<_Tp, _Alloc>::value_type = var*]’ (near match)
1203 | push_back(value_type&& __x)
| ^~~~~~~~~
/usr/include/c++/10/bits/stl_vector.h:1203:7: note: conversion of argument 1 would be ill-formed:
test.cpp:10:30: error: invalid conversion from ‘const var*’ to ‘std::vector<var*>::value_type’ {aka ‘var*’} [-fpermissive]
10 | variables_.push_back(&v);
| ^~
| |
| const var*
test.cpp:11:5: warning: no return statement in function returning non-void [-Wreturn-type]
11 | }
| ^
I have read several posts on this site telling me why this wont work. One of which is that elements of the vector have to be copy assignable. So I understand WHY, but I don't understand how to get around it.
There must be a way around this.
You take a const var&, but your vector stores var* (without the const). Either your vector needs to store pointers to constants
static std::vector<const var*> variables_;
or your operator- needs to take a non-constant reference
friend var operator-(var& v) { ... }
You should do the first thing if you never plan to modify var through the variables_ vector, or the second otherwise.

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']]

Don't understand this problem with ranges::v3

I have the following code fragment using ranges::v3:
#include <range/v3/view/all.hpp>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/join.hpp>
#include <range/v3/range/conversion.hpp>
#include <unordered_map>
#include <limits>
#include <stdint.h>
#include <sys/socket.h>
#include <string>
struct EncodedValueDecoder: std::unordered_map<int, uint8_t> {
using Base_t = std::unordered_map<int, uint8_t>;
EncodedValueDecoder(int mask, const Base_t& values) :
Base_t(values), mask_(mask == 0 ? std::numeric_limits<int>::max() : mask) {
}
std::string findAll(const int target) const {
return *this | ranges::views::filter([&target, this](const typename Base_t::value_type& item) {
return bitSet(item.first, target);
}) | ranges::views::join(",") | ranges::to<std::string>();
}
int maskedValue(const int target) const {
return static_cast<int>(target & mask_);
}
bool bitSet(const int bit, const int target) const {
return bit & target & mask_;
}
int mask_;
};
I get the following errors
g++ -std=c++23 -O0 -g3 -pedantic -pedantic-errors -Wall -Wextra -Werror -Wconversion -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wlogical-op -Wmissing-declarations -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wshadow -Wsign-conversion -Wsign-promo -Wswitch-default -Wfloat-equal -c -pthread -Winvalid-pch -fmessage-length=0 -Wdouble-promotion -Wimplicit-fallthrough=5 -Wuninitialized -Winit-self -Wsuggest-override -Wduplicated-branches -Wduplicated-cond -Wtrampolines -Wcast-qual -Wuseless-cast -Wsized-deallocation -ftemplate-backtrace-limit=0 -fPIC -o src/main.o ../src/main.cpp
../src/main.cpp: In member function ‘std::string EncodedValueDecoder::findAll(int) const’:
../src/main.cpp:20:20: error: no match for ‘operator|’ (operand types are ‘ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >’ and ‘ranges::views::view_closure<ranges::detail::bind_back_fn_<ranges::views::join_base_fn, ranges::detail::reference_wrapper_<const char [2]> > >’)
18 | return *this | ranges::views::filter([&target, this](const typename Base_t::value_type& item) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >
19 | return bitSet(item.first, target);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 | }) | ranges::views::join(",") | ranges::to<std::string>();
| ~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~
| |
| ranges::views::view_closure<ranges::detail::bind_back_fn_<ranges::views::join_base_fn, ranges::detail::reference_wrapper_<const char [2]> > >
In file included from /usr/include/range/v3/view/all.hpp:28,
from ../src/main.cpp:1:
/usr/include/range/v3/view/view.hpp:142:35: note: candidate: ‘template<class ViewFn, class Pipeable> constexpr concepts::return_t<ranges::views::view_closure<ranges::composed<Pipeable, ViewFn> >, typename std::enable_if<(is_pipeable_v<Pipeable> && concepts::detail::CPP_true_fn(concepts::detail::Nil{})), void>::type> ranges::views::view_closure_base_ns::operator|(ranges::views::view_closure<Fun>, Pipeable)’
142 | friend constexpr auto operator|(view_closure<ViewFn> vw, Pipeable pipe)
| ^~~~~~~~
/usr/include/range/v3/view/view.hpp:142:35: note: template argument deduction/substitution failed:
../src/main.cpp:20:45: note: ‘ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >’ is not derived from ‘ranges::views::view_closure<Fun>’
20 | }) | ranges::views::join(",") | ranges::to<std::string>();
| ^
/usr/include/range/v3/view/view.hpp:127:13: note: candidate: ‘template<class Rng, class ViewFn> constexpr concepts::return_t<Rng, typename std::enable_if<((range<Rng> && (! viewable_range<Rng>)) && concepts::detail::CPP_true_fn(concepts::detail::Nil{})), void>::type> ranges::views::view_closure_base_ns::operator|(Rng&&, const ranges::views::view_closure<ViewFn>&)’ (deleted)
127 | operator|(Rng &&, view_closure<ViewFn> const &) // ******* READ THIS ********
| ^~~~~~~~
/usr/include/range/v3/view/view.hpp:127:13: note: template argument deduction/substitution failed:
/usr/include/range/v3/view/view.hpp: In substitution of ‘template<class Rng, class ViewFn> constexpr concepts::return_t<Rng, typename std::enable_if<((range<Rng> && (! viewable_range<Rng>)) && concepts::detail::CPP_true_fn(concepts::detail::Nil{})), void>::type> ranges::views::view_closure_base_ns::operator|(Rng&&, const ranges::views::view_closure<ViewFn>&) [with Rng = ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >; ViewFn = ranges::detail::bind_back_fn_<ranges::views::join_base_fn, ranges::detail::reference_wrapper_<const char [2]> >]’:
../src/main.cpp:20:31: required from here
/usr/include/range/v3/view/view.hpp:127:13: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
/usr/include/range/v3/view/view.hpp:117:35: note: candidate: ‘template<class Rng, class ViewFn> requires (viewable_range<Rng>) && (invocable_view_closure<ViewFn, Rng>) constexpr auto ranges::views::view_closure_base_ns::operator|(Rng&&, ranges::views::view_closure<ViewFn>)’
117 | friend constexpr auto operator|(Rng && rng, view_closure<ViewFn> vw)
| ^~~~~~~~
/usr/include/range/v3/view/view.hpp:117:35: note: template argument deduction/substitution failed:
/usr/include/range/v3/view/view.hpp:117:35: note: constraints not satisfied
In file included from /usr/include/range/v3/range_fwd.hpp:22,
from /usr/include/range/v3/view/all.hpp:20:
/usr/include/range/v3/functional/concepts.hpp: In substitution of ‘template<class Rng, class ViewFn> requires (viewable_range<Rng>) && (invocable_view_closure<ViewFn, Rng>) constexpr auto ranges::views::view_closure_base_ns::operator|(Rng&&, ranges::views::view_closure<ViewFn>) [with Rng = ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >; ViewFn = ranges::detail::bind_back_fn_<ranges::views::join_base_fn, ranges::detail::reference_wrapper_<const char [2]> >]’:
../src/main.cpp:20:31: required from here
/usr/include/range/v3/functional/concepts.hpp:40:5: required for the satisfaction of ‘invocable_requires_<Fun, Args ...>’ [with Fun = ranges::detail::bind_back_fn_<ranges::views::join_base_fn, ranges::detail::reference_wrapper_<const char[2]> >; Args = {ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll::._anon_127>}]
/usr/include/range/v3/functional/concepts.hpp:48:17: required for the satisfaction of ‘invocable<ViewFn, Rng>’ [with ViewFn = ranges::detail::bind_back_fn_<ranges::views::join_base_fn, ranges::detail::reference_wrapper_<const char[2]> >; Rng = ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll::._anon_127>]
/usr/include/range/v3/view/view.hpp:83:17: required for the satisfaction of ‘invocable_view_closure<ViewFn, Rng>’ [with ViewFn = ranges::detail::bind_back_fn_<ranges::views::join_base_fn, ranges::detail::reference_wrapper_<const char[2]> >; Rng = ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll::._anon_127>]
/usr/include/range/v3/functional/concepts.hpp:40:5: in requirements with ‘Fun&& fn’ [with Args = {ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll::._anon_127>}; Fun = ranges::detail::bind_back_fn_<ranges::views::join_base_fn, ranges::detail::reference_wrapper_<const char[2]> >]
/usr/include/range/v3/functional/concepts.hpp:40:5: note: the required expression ‘ranges::invoke((Fun&&)(fn), (declval<Args>)()...)’ is invalid
40 | CPP_requires(invocable_,
| ^~~~~~~~~~~~
cc1plus: note: set ‘-fconcepts-diagnostics-depth=’ to at least 2 for more detail
In file included from /usr/include/meta/meta.hpp:18,
from /usr/include/range/v3/view/all.hpp:18:
/usr/include/c++/12.1.0/cstddef:132:3: note: candidate: ‘constexpr std::byte std::operator|(byte, byte)’
132 | operator|(byte __l, byte __r) noexcept
| ^~~~~~~~
/usr/include/c++/12.1.0/cstddef:132:18: note: no known conversion for argument 1 from ‘ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >’ to ‘std::byte’
132 | operator|(byte __l, byte __r) noexcept
| ~~~~~^~~
In file included from /usr/include/c++/12.1.0/streambuf:41,
from /usr/include/c++/12.1.0/bits/streambuf_iterator.h:35,
from /usr/include/c++/12.1.0/iterator:66,
from /usr/include/range/v3/range/access.hpp:21,
from /usr/include/range/v3/view/all.hpp:22:
/usr/include/c++/12.1.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)
| ^~~~~~~~
/usr/include/c++/12.1.0/bits/ios_base.h:87:27: note: no known conversion for argument 1 from ‘ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >’ to ‘std::_Ios_Fmtflags’
87 | operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
| ~~~~~~~~~~~~~~^~~
/usr/include/c++/12.1.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)
| ^~~~~~~~
/usr/include/c++/12.1.0/bits/ios_base.h:130:27: note: no known conversion for argument 1 from ‘ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >’ to ‘std::_Ios_Openmode’
130 | operator|(_Ios_Openmode __a, _Ios_Openmode __b)
| ~~~~~~~~~~~~~~^~~
/usr/include/c++/12.1.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)
| ^~~~~~~~
/usr/include/c++/12.1.0/bits/ios_base.h:170:26: note: no known conversion for argument 1 from ‘ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >’ to ‘std::_Ios_Iostate’
170 | operator|(_Ios_Iostate __a, _Ios_Iostate __b)
| ~~~~~~~~~~~~~^~~
In file included from /usr/include/c++/12.1.0/bits/shared_ptr_atomic.h:33,
from /usr/include/c++/12.1.0/memory:78,
from /usr/include/range/v3/utility/addressof.hpp:15,
from /usr/include/range/v3/iterator/basic_iterator.hpp:29,
from /usr/include/range/v3/iterator/reverse_iterator.hpp:20,
from /usr/include/range/v3/range/access.hpp:37:
/usr/include/c++/12.1.0/bits/atomic_base.h:98:3: note: candidate: ‘constexpr std::memory_order std::operator|(memory_order, __memory_order_modifier)’
98 | operator|(memory_order __m, __memory_order_modifier __mod)
| ^~~~~~~~
/usr/include/c++/12.1.0/bits/atomic_base.h:98:26: note: no known conversion for argument 1 from ‘ranges::filter_view<ranges::ref_view<const EncodedValueDecoder>, EncodedValueDecoder::findAll(int) const::<lambda(const std::unordered_map<int, unsigned char>::value_type&)> >’ to ‘std::memory_order’
98 | operator|(memory_order __m, __memory_order_modifier __mod)
| ~~~~~~~~~~~~~^~~
../src/main.cpp: In member function ‘int EncodedValueDecoder::maskedValue(int) const’:
../src/main.cpp:23:24: error: useless cast to type ‘int’ [-Werror=useless-cast]
23 | return static_cast<int>(target & mask_);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
It appears to be complaining about the absence of a suitable overload for operator|. Given that I adapted this code from some examples I've seen in blogs dealing with ranges::v3, I've obviously misunderstood something. Can anyone point out my error?
The code I've posted is nonsense which is why it wouldn't compile. Kudos to JaMiT. If I could find a way to award a gold star, I would.

ranges views size does not compile

#include <iostream>
#include <cstdlib>
#include <vector>
#include <ranges>
#include <algorithm>
using namespace std;
int main()
{
vector<int> ints = {1,2,3,4,5};
auto v = ints | views::take_while([](int i){return i<3;}) ;
for (int i : v) std::cout << i << ' ';
std::cout << '\n';
int size = v.size();
std::cout << size << std::endl;
}
v.size() does not compile. How do you do this ?
prog.cc: In function 'int main()':
prog.cc:16:23: error: no matching function for call to 'std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >::size()'
16 | int size = v.size();
| ^
In file included from prog.cc:5:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:144:7: note: candidate: 'constexpr auto std::ranges::view_interface<_Derived>::size() requires (forward_range<_Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<_Tp&>)())), decltype(std::__detail::__ranges_begin((declval<_Container&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]'
144 | size()
| ^~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:144:7: note: constraints not satisfied
In file included from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_iterator_base_types.h:71,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_algobase.h:65,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/char_traits.h:39,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ios:40,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ostream:38,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/iostream:39,
from prog.cc:2:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h: In instantiation of 'constexpr auto std::ranges::view_interface<_Derived>::size() requires (forward_range<_Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<_Tp&>)())), decltype(std::__detail::__ranges_begin((declval<_Container&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]':
prog.cc:16:23: required from here
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:555:13: required for the satisfaction of 'sized_sentinel_for<std::ranges::sentinel_t<_Tp>, decltype (std::__detail::__ranges_begin(declval<_Container&>()))>' [with _Tp = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>; _Container = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:557:8: in requirements with 'const _Iter& __i', 'const _Sent& __s' [with _Arg = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >; _Sent = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>::_Sentinel<true>; _Iter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:559:13: note: the required expression '(__s - __i)' is invalid
559 | { __s - __i } -> same_as<iter_difference_t<_Iter>>;
| ~~~~^~~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:560:13: note: the required expression '(__i - __s)' is invalid
560 | { __i - __s } -> same_as<iter_difference_t<_Iter>>;
| ~~~~^~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
In file included from prog.cc:5:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:150:7: note: candidate: 'constexpr auto std::ranges::view_interface<_Derived>::size() const requires (forward_range<const _Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<const _Range&>)())), decltype(std::__detail::__ranges_begin((declval<const _Range&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]'
150 | size() const
| ^~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:150:7: note: constraints not satisfied
In file included from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_iterator_base_types.h:71,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_algobase.h:65,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/char_traits.h:39,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ios:40,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ostream:38,
from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/iostream:39,
from prog.cc:2:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h: In instantiation of 'constexpr auto std::ranges::view_interface<_Derived>::size() const requires (forward_range<const _Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<const _Range&>)())), decltype(std::__detail::__ranges_begin((declval<const _Range&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]':
prog.cc:16:23: required from here
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:555:13: required for the satisfaction of 'sized_sentinel_for<std::ranges::sentinel_t<const _Range>, decltype (std::__detail::__ranges_begin(declval<const _Range&>()))>' [with _Range = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:557:8: in requirements with 'const _Iter& __i', 'const _Sent& __s' [with _Arg = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >; _Sent = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>::_Sentinel<true>; _Iter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:559:13: note: the required expression '(__s - __i)' is invalid
559 | { __s - __i } -> same_as<iter_difference_t<_Iter>>;
| ~~~~^~~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:560:13: note: the required expression '(__i - __s)' is invalid
560 | { __i - __s } -> same_as<iter_difference_t<_Iter>>;
| ~~~~^~~~~
Since take_while and its ilk shorten the size of the list in unpredictable ways, those range adaptors cannot return a sized_range, even if the input itself is sized. sized_range requires that the range can compute the size in O(1) time, and take_while's view cannot do that.
So if you want the size (and you shouldn't), you will have to compute it yourself. You could also use std::ranges::distance on the range.

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>