Date: Sun, 13 Apr 2025 13:15:09 -0400
There’s two different answers, one for std::integral and one for my StandardInteger:
* std::is_integral
This grew out of boost library around 2000 authored by John Maddock and Steve Cleary:
https://www.boost.org/doc/libs/1_88_0/libs/type_traits/doc/html/index.html
The year of development is important because libraries are made with the tools/language available at the time. In 2000, type_traits was state of the art. Even enable_if was not invented until about 3 years after this. So programatically inspecting a type for its operations was not in the tool box.
Nevertheless, type_traits was a huge success because it enabled a vast amount of introspection with a relatively uniform API that was not previously availalbe. This library was so successful that it was standardized in C++11. In 2011 work had begun on concepts, but attempts to standardize it in that time frame failed. The concepts technology was not yet mature.
* bbi::detail::StandardInteger
This library is an integer emulator that seeks to eliminate (or at least greatly reduce) undefined behavior for things like signed integer overflow. One of the important behaviors of this library is how it handles conversions, both implicit and explicit. There are conversions among the bbi types, and to/from the built-in integral types.
In order to generically program the conversions between the bbi types and the built-in integral types it is important to identify and distinguish the built-in integral types, as opposed to identifying operations on a generic type.
For example a signed bbi type of width M can implicitly convert to a signed bbi type of with N when N > M (because it is a value-preserving conversion). However all conversions from bbi types to built-in integral types are explicit, not implicit, because exiting the safety of the bbi type system is considered a more dangerous conversion, even if it is a value-preserving conversion.
* Generalized arithmetic concept
All that being said above, there do exist important use cases that need a generalized arithmetic concept that could be a built-in arithmetic type, or a class type emulating a built-in arithmetic type. Here the operations that the type has is the important ingredient, and there is little to no need to distinguish between class types and std::integral types.
The std::chrono::duration::rep is such a use case: https://eel.is/c++draft/time.duration.general#2.sentence-1. And quite frankly we have struggled with this specification. But nevertheless, it is very important that one be able to use in <chrono> class types such as the bbi integral emulator types that I mention above.
So both the “type list” and “operator” approaches are important tools in the toolbox. On the “operator” side I should point out that a class type need not support all opertions to be used with a library like <chrono> if it is only going to be used with a subset of that library. For example if you only add two durations using your custom rep, your custom rep need not support subtraction.
Howard
On Apr 13, 2025, at 7:26 AM, Ivan Matek <libbooze_at_[hidden]> wrote:
>
> May I ask your opinion why std:: and your concepts are basically a fancy type lists and not something more abstract?
> For example for std::floating_point I would expect certain operations like construction addition, division work “as expected” so that any 3rd party type is matched.
> I presume the issue is agreeing what a “as expected” is so std:: picked easier type list approach.
>
> On Sat, 12 Apr 2025 at 19:08, Howard Hinnant via Std-Proposals <std-proposals_at_[hidden]> wrote:
> Ancedote:
>
> std::integral recently fell out of favor with me and I wrote my own concept that better suited my needs:
>
> https://github.com/HowardHinnant/bbi/blob/master/bbi.h#L176-L191
>
> StandardSignedInteger
> StandardUnsignedInteger
> StandardInteger
>
> The difference here is that my concepts exclue bool and the character types. This distinction was at best not clear in C++11, and not modeled by the type_traits introduced then. For my work today, it is important to not include bool and the character types as “integral types” as their semantics are not consistent with the representaiton of integral numbers.
>
> I mention this ancedote as a word of caution for building further concepts on top of type_traits. type_traits was a good model of the type system when they were introduced, but may not be today, 15 years later.
>
> Howard
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
* std::is_integral
This grew out of boost library around 2000 authored by John Maddock and Steve Cleary:
https://www.boost.org/doc/libs/1_88_0/libs/type_traits/doc/html/index.html
The year of development is important because libraries are made with the tools/language available at the time. In 2000, type_traits was state of the art. Even enable_if was not invented until about 3 years after this. So programatically inspecting a type for its operations was not in the tool box.
Nevertheless, type_traits was a huge success because it enabled a vast amount of introspection with a relatively uniform API that was not previously availalbe. This library was so successful that it was standardized in C++11. In 2011 work had begun on concepts, but attempts to standardize it in that time frame failed. The concepts technology was not yet mature.
* bbi::detail::StandardInteger
This library is an integer emulator that seeks to eliminate (or at least greatly reduce) undefined behavior for things like signed integer overflow. One of the important behaviors of this library is how it handles conversions, both implicit and explicit. There are conversions among the bbi types, and to/from the built-in integral types.
In order to generically program the conversions between the bbi types and the built-in integral types it is important to identify and distinguish the built-in integral types, as opposed to identifying operations on a generic type.
For example a signed bbi type of width M can implicitly convert to a signed bbi type of with N when N > M (because it is a value-preserving conversion). However all conversions from bbi types to built-in integral types are explicit, not implicit, because exiting the safety of the bbi type system is considered a more dangerous conversion, even if it is a value-preserving conversion.
* Generalized arithmetic concept
All that being said above, there do exist important use cases that need a generalized arithmetic concept that could be a built-in arithmetic type, or a class type emulating a built-in arithmetic type. Here the operations that the type has is the important ingredient, and there is little to no need to distinguish between class types and std::integral types.
The std::chrono::duration::rep is such a use case: https://eel.is/c++draft/time.duration.general#2.sentence-1. And quite frankly we have struggled with this specification. But nevertheless, it is very important that one be able to use in <chrono> class types such as the bbi integral emulator types that I mention above.
So both the “type list” and “operator” approaches are important tools in the toolbox. On the “operator” side I should point out that a class type need not support all opertions to be used with a library like <chrono> if it is only going to be used with a subset of that library. For example if you only add two durations using your custom rep, your custom rep need not support subtraction.
Howard
On Apr 13, 2025, at 7:26 AM, Ivan Matek <libbooze_at_[hidden]> wrote:
>
> May I ask your opinion why std:: and your concepts are basically a fancy type lists and not something more abstract?
> For example for std::floating_point I would expect certain operations like construction addition, division work “as expected” so that any 3rd party type is matched.
> I presume the issue is agreeing what a “as expected” is so std:: picked easier type list approach.
>
> On Sat, 12 Apr 2025 at 19:08, Howard Hinnant via Std-Proposals <std-proposals_at_[hidden]> wrote:
> Ancedote:
>
> std::integral recently fell out of favor with me and I wrote my own concept that better suited my needs:
>
> https://github.com/HowardHinnant/bbi/blob/master/bbi.h#L176-L191
>
> StandardSignedInteger
> StandardUnsignedInteger
> StandardInteger
>
> The difference here is that my concepts exclue bool and the character types. This distinction was at best not clear in C++11, and not modeled by the type_traits introduced then. For my work today, it is important to not include bool and the character types as “integral types” as their semantics are not consistent with the representaiton of integral numbers.
>
> I mention this ancedote as a word of caution for building further concepts on top of type_traits. type_traits was a good model of the type system when they were introduced, but may not be today, 15 years later.
>
> Howard
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2025-04-13 17:15:46