strong_type icon indicating copy to clipboard operation
strong_type copied to clipboard

Overriding std::is_arithmetic<> for program-defined type is undefined behaviour?

Open saxbophone opened this issue 2 years ago • 5 comments

In the README, it's specified:

For modifier strong::arithmetic, the type trait std::is_arithmetic<> is true.

According to the standard, this is undefined behaviour:

(source — cppreference.com)

Maybe std::numeric_limits<> should be specialised instead, to provide type-traits? That one is open to extension, provided one doesn't reopen the std namespace and just specialises the fully-qualified name of the template...

saxbophone avatar Jun 03 '22 16:06 saxbophone

Right. Bummer. I should've known this. Dropping it is also a potentially breaking change for some users, but it's the way to go. Thanks for reporting.

rollbear avatar Jun 18 '22 19:06 rollbear

related to specializing std::is_arithmetic, this code gives me a compile error with catch2 v3

TEST_CASE( "testme", "" )
{
    using test_type
        = strong::type< std::int8_t, struct tag, strong::arithmetic, strong::default_constructible, strong::equality >;

    constexpr test_type a;
    test_type           b;
    CHECK( a == b );
}
my/test.cpp: error: use of overloaded operator '<=' is ambiguous (with operand types 'Catch::Decomposer' and 'const test_type' (aka 'const type<signed char, tag, strong::arithmetic, strong::default_constructible, strong::equality>'))
    catchAssertionHandler.handleExpr( Catch::Decomposer() <= a == b );
                                      ~~~~~~~~~~~~~~~~~~~ ^  ~
/path/to/catch2-v3/src/catch2/../catch2/internal/catch_decomposer.hpp:247:21: note: candidate function [with T = const strong::type<signed char, tag, strong::arithmetic, strong::default_constructible, strong::equality> &, $1 = 0]
        friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> {
                    ^
/path/to/catch2-v3/src/catch2/../catch2/internal/catch_decomposer.hpp:252:21: note: candidate function [with T = strong::type<signed char, tag, strong::arithmetic, strong::default_constructible, strong::equality>, $1 = 0]
        friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> {
                    ^
1 error generated.

timblechmann avatar Sep 21 '22 01:09 timblechmann

Thanks @timblechmann , that was a very unexpected result of this. I'll get to fixing it as soon as I'm out of meetings.

rollbear avatar Sep 21 '22 07:09 rollbear

Fixed on main now. Leaving this open until a release is tagged.

rollbear avatar Sep 21 '22 07:09 rollbear

Hurrah! How do you feel about going down the route of specializing std::numeric_limits<> instead? IIRC, there are members within that struct that can provide similar traits-like functionality as you were providing with is_arithmetic, though I forget the names of the exact members. I've got a previous specialisation of that struct I did for a personal project, maybe I'll dig that out (there's loads of definitions ☹️) and have a go hacking on strong_type...

saxbophone avatar Sep 23 '22 15:09 saxbophone

@saxbophone feel free to open a separate issue about that.

rollbear avatar Oct 20 '22 08:10 rollbear

Fix included in release v5

rollbear avatar Oct 20 '22 08:10 rollbear

@saxbophone feel free to open a separate issue about that.

Thanks, I think I will and I will also try and send a PR with the structure of the type traits stuff I mentioned.

saxbophone avatar Oct 20 '22 09:10 saxbophone