Skip to content

Conversation

@Romain-Geissler-1A
Copy link
Contributor

This allows to workaround the following error when using clang >= 21 on the following code:

#include <string>
#include <iostream>
#include "boost/lexical_cast.hpp"

enum SomeEnum
{
    OneValue
};

int main()
{
    std::cout << boost::lexical_cast<std::string>(SomeEnum::OneValue) << std::endl;
}

Results in:

/app/boost/include/boost/type_traits/is_signed.hpp:37:25: error: in-class initializer for static data member is not a constant expression
   37 |    static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));

... (snapped)

/app/boost/include/boost/type_traits/is_signed.hpp:37:38: note: integer value -1 is outside the valid range of values [0, 1] for the enumeration type 'SomeEnum'
   37 |    static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));

@Romain-Geissler-1A Romain-Geissler-1A force-pushed the reduce-type-traits-usage branch 10 times, most recently from 47f8885 to 6324324 Compare September 5, 2025 21:47

template <class Type>
typename boost::enable_if_c<boost::is_signed<Type>::value && !boost::is_enum<Type>::value, bool>::type
typename std::enable_if<!std::is_floating_point<Type>::value && std::is_signed<Type>::value && !std::is_enum<Type>::value, bool>::type
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to add the !std::is_floating_point<Type>::value check here, since boost::is_signed and std::is_signed behave differently. We have this (which you can double check on Compiler Explorer here: https://godbolt.org/z/xjYWGrTce)

static_assert(std::is_signed<float>::value);
static_assert(!boost::is_signed<float>::value);

(same for all kind of floating point types).

If we don't change this, then the tests is_optimized_stream in test/stream_traits_test.cpp are failing for the float to string conversions in optimized mode.

Romain-Geissler-1A added a commit to Romain-Geissler-1A/type_traits that referenced this pull request Sep 5, 2025
With clang >= 21, using is_signed/is_unsigned with "small" enums
(having an underlying type smaller than an int) results in strong error,
after being reported as warnings for years (see boostorg#171).

Since boost::is_signed/is_unsigned differs explicitly from the std one,
and can return "true" for enums (contrary to the std one), keep this
boost behavior and implement a special check for enums.

This allows in particular boost::lexical_cast to keep working when
converting non-scoped enums from int to strings with clang >= 21,
see boostorg/lexical_cast#87).
@Romain-Geissler-1A Romain-Geissler-1A force-pushed the reduce-type-traits-usage branch 3 times, most recently from c529039 to 7d74d46 Compare September 12, 2025 13:18
@@ -0,0 +1,80 @@
// Copyright Romain Geissler, 2025.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdimov Since this is a copy/paste from your work, should I mention your name in the copyright instead ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to keep your line and add a separate one for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, there are now 2 copyright lines, mentionning each of us.

This allows to workaround the following error when using clang >= 21 on
the following code:

    #include <string>
    #include <iostream>
    #include "boost/lexical_cast.hpp"

    enum SomeEnum
    {
        OneValue
    };

    int main()
    {
        std::cout << boost::lexical_cast<std::string>(SomeEnum::OneValue) << std::endl;
    }

    /app/boost/include/boost/type_traits/is_signed.hpp:37:25: error: in-class initializer for static data member is not a constant expression
       37 |    static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));

    ... (snapped)

    /app/boost/include/boost/type_traits/is_signed.hpp:37:38: note: integer value -1 is outside the valid range of values [0, 1] for the enumeration type 'SomeEnum'
       37 |    static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));
@Romain-Geissler-1A
Copy link
Contributor Author

Ping

@apolukhin apolukhin merged commit 8fc8a19 into boostorg:develop Oct 5, 2025
8 of 9 checks passed
@apolukhin
Copy link
Member

Many thanks for the PR! It should improve compile times for big modern projects that use LexicalCast. I was attempting to do the proposed change a few years ago, but the int128_t issues stopped me from doing so

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants