Date: Mon, 22 Jun 2026 10:14:50 +0000
"Okay, but Endian Views don't provide this functionality of representing as the type rather than as bytes."
I don't understand how you conclude this. The after part of the first Tony Table in the paper is:
constexpr vector<uint32_t> utf16be_to_utf32be(
const vector<uint16_t>& utf16be_data) {
return utf16be_data
| views::from_big_endian
| views::as_char16_t
| views::to_utf32
| views::transform(
[](const char32_t c) {
return static_cast<uint32_t>(c);
})
| views::to_big_endian
| ranges::to<vector>();
}
Note that from_big_endian doesn't mention the type because this is inferred from the value type of the upstream range (i.e. utf16be_data). This is exactly the property I was referring to in Boost.Endian. If the endian views accepted raw bytes (under what I understand is the argument you're making) then views::from_big_endian would:
- Need to be templated on the destination type (i.e. it would be views::from_big_endian<std::uint16_t>), and
- Would need to check for improperly-sized input (i.e. the case where the size of the upstream range is odd)
--Robert
________________________________
From: Jan Schultke <janschultke_at_[hidden]>
Sent: Monday, June 22, 2026 05:54
To: Robert A.H. Leahy <rleahy_at_[hidden]>
Cc: sg16_at_[hidden] <sg16_at_[hidden]>; SG9 ranges <sg9_at_[hidden]>; Tom Honermann <tom_at_[hidden]>
Subject: Re: [isocpp-sg16] Thoughts on P4030R0: Endian Views
On Mon, 22 Jun 2026 at 11:37, Robert A.H. Leahy <rleahy_at_[hidden]<mailto:rleahy_at_[hidden]>> wrote:
I don't understand how anything about the problem domain implies that I need to eagerly convert endianness.
In order to use the data I need to convert the endianness, but that doesn't mean that I need to eagerly do so since it's not a given that I will use the data.
If your use case is that you want to avoid processing all the data but only want to examine e.g. one line of a text file, you can equally accomplish that by searching for that line and then eagerly converting that one line.
And anyway, the common use case is that I have some serialized data and I decode it into something I can actually use in my application. The use case where you do that on-demand is highly specialized in my opinion, and it incurs major complexity cost to deserialize file portions on-demand (which views might be useful for).
Also note that since the functionality we're talking about is presented in the form of a view, and therefore we're in the domain of ranges, nothing about constructing such a pipeline implies that conversion will actually occur. Loading the "wire"-endian data might be lazy in the same way the endianness conversion is.
This would be more motivating if endianness conversion was more expensive. Then you could avoid this super expensive operation if you first had a views::filter in the pipeline, or something like that.
However, we're talking about something that's either a no-op or a single-cycle bswap instruction.
And if your goal is to only endian-convert a subrange of the data, that can equally be accomplished without views.
Note that representing the wire-endian data by its destination type, rather than by bytes, allows for the view pipeline to discover the type implicitly, rather than having to restate it. This technique is also used by the interface of Boost.Endian (i.e. I don't need to explicitly tell boost::endian::big_to_native that it's converting to std::uint16_t because I pass it a big-endian std::uint16_t and it can use template argument deduction to discover this).
Okay, but Endian Views don't provide this functionality of representing as the type rather than as bytes. You still need to do all the chunking and joining and reinterpreting yourself before you even get to use an endian view. I'm more interested in solving that part.
Thankfully, Boost.Endian also provides endian_load and endian_store functions, which I find much more relevant.
I don't understand how you conclude this. The after part of the first Tony Table in the paper is:
constexpr vector<uint32_t> utf16be_to_utf32be(
const vector<uint16_t>& utf16be_data) {
return utf16be_data
| views::from_big_endian
| views::as_char16_t
| views::to_utf32
| views::transform(
[](const char32_t c) {
return static_cast<uint32_t>(c);
})
| views::to_big_endian
| ranges::to<vector>();
}
Note that from_big_endian doesn't mention the type because this is inferred from the value type of the upstream range (i.e. utf16be_data). This is exactly the property I was referring to in Boost.Endian. If the endian views accepted raw bytes (under what I understand is the argument you're making) then views::from_big_endian would:
- Need to be templated on the destination type (i.e. it would be views::from_big_endian<std::uint16_t>), and
- Would need to check for improperly-sized input (i.e. the case where the size of the upstream range is odd)
--Robert
________________________________
From: Jan Schultke <janschultke_at_[hidden]>
Sent: Monday, June 22, 2026 05:54
To: Robert A.H. Leahy <rleahy_at_[hidden]>
Cc: sg16_at_[hidden] <sg16_at_[hidden]>; SG9 ranges <sg9_at_[hidden]>; Tom Honermann <tom_at_[hidden]>
Subject: Re: [isocpp-sg16] Thoughts on P4030R0: Endian Views
On Mon, 22 Jun 2026 at 11:37, Robert A.H. Leahy <rleahy_at_[hidden]<mailto:rleahy_at_[hidden]>> wrote:
I don't understand how anything about the problem domain implies that I need to eagerly convert endianness.
In order to use the data I need to convert the endianness, but that doesn't mean that I need to eagerly do so since it's not a given that I will use the data.
If your use case is that you want to avoid processing all the data but only want to examine e.g. one line of a text file, you can equally accomplish that by searching for that line and then eagerly converting that one line.
And anyway, the common use case is that I have some serialized data and I decode it into something I can actually use in my application. The use case where you do that on-demand is highly specialized in my opinion, and it incurs major complexity cost to deserialize file portions on-demand (which views might be useful for).
Also note that since the functionality we're talking about is presented in the form of a view, and therefore we're in the domain of ranges, nothing about constructing such a pipeline implies that conversion will actually occur. Loading the "wire"-endian data might be lazy in the same way the endianness conversion is.
This would be more motivating if endianness conversion was more expensive. Then you could avoid this super expensive operation if you first had a views::filter in the pipeline, or something like that.
However, we're talking about something that's either a no-op or a single-cycle bswap instruction.
And if your goal is to only endian-convert a subrange of the data, that can equally be accomplished without views.
Note that representing the wire-endian data by its destination type, rather than by bytes, allows for the view pipeline to discover the type implicitly, rather than having to restate it. This technique is also used by the interface of Boost.Endian (i.e. I don't need to explicitly tell boost::endian::big_to_native that it's converting to std::uint16_t because I pass it a big-endian std::uint16_t and it can use template argument deduction to discover this).
Okay, but Endian Views don't provide this functionality of representing as the type rather than as bytes. You still need to do all the chunking and joining and reinterpreting yourself before you even get to use an endian view. I'm more interested in solving that part.
Thankfully, Boost.Endian also provides endian_load and endian_store functions, which I find much more relevant.
Received on 2026-06-22 10:14:55
