Boost logo

Boost :

From: Rainer Deyke (rdeyke_at_[hidden])
Date: 2024-03-22 11:11:55


On 21.03.24 14:43, René Ferdinand Rivera Morell via Boost wrote:
> On Thu, Mar 21, 2024 at 3:35 AM Rainer Deyke via Boost
> <boost_at_[hidden]> wrote:
>> This is not so good, because it mixes the options of different
>> encodings, resulting in potentially nonsensical combinations:
>>
>> result = baseX_encode<64>(source, encoding_options::no_padding);
>> result2 = baseX_encode<16>(source, encoding_options::lower_case);
>>
>> // The lower_case option is non-sensical for base 64; can this
>> // error be caught at compile time?
>> // result3 = baseX_encode<64>(source, encoding_options::lower_case);
>
> It can be caught at compile time. But not with that interface.

Actually it can be caught at compile time even with that interface, if
encoding_options is a namespace instead of an enum type and
encoding_options::lower_case has a distinct type from
encoding_options::no_padding. For example:

template<uint8_t> class encoding_option {};
constexpr encoding_option<0x01> lower_case;
constexpr encoding_option<0x02> no_padding;

template<uint8_t a, uint8_t b>
constexpr encoding_option<a | b> operator|(
     encoding_option<a>,
     encoding_option<b>) {
   return {};
}

However, I don't see any benefit whatsoever in having a single
encoding-neutral template as the main entry point. Specifying 64 as an
integer is especially problematic because base-X as a generalization
does not exist. Rather, base-64 and base-16 are distinct members of the
larger family of bindary-to-text encodings that also includes
uuencoding, BinHex, and percent encoding.

> Yeah, as Adrey mentions, making this a runtime choice is sufficiently
> rare that it's not worth even thinking about it. I certainly never had
> a use for a runtime choice for that. As for a sane interface.. I would
> think having encoder/decoder templates (perhaps as functors) is the
> way to go. For example:
>
> auto base64enc = boost::thing::base_encoder<64,
> boost::thing::encoding_options::no_padding>();
> auto encoded = base64enc.encode(data);
> auto decoded = base64enc.decode(encoded);
>
> This makes it possible to pass the encoder object to generic code
> without worrying about calling some specific base64 or base16
> functions. Having the template args also makes it possible to check
> valid combinations. It also makes it easier to specialize performant
> combinations and still cover everything else with not-so-performant
> default implementation.

Having an encoder object makes sense. Defining a reusable concept for
this encoder object makes sense. Defining a single class template for
the encoder object does not make sense, because the set of encoder
objects I might want to use is open.

-- 
Rainer Deyke (rainerd_at_[hidden])

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk