Reduce dependency on Boost.TypeTraits now that C++ >= 11 is required.#87
Conversation
47f8885 to
6324324
Compare
|
|
||
| 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 |
There was a problem hiding this comment.
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.
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).
c529039 to
7d74d46
Compare
| @@ -0,0 +1,80 @@ | |||
| // Copyright Romain Geissler, 2025. | |||
There was a problem hiding this comment.
@pdimov Since this is a copy/paste from your work, should I mention your name in the copyright instead ?
There was a problem hiding this comment.
It's better to keep your line and add a separate one for me.
There was a problem hiding this comment.
Alright, there are now 2 copyright lines, mentionning each of us.
7d74d46 to
1849b91
Compare
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));
1849b91 to
efb0b23
Compare
|
Ping |
|
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 |
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).
This allows to workaround the following error when using clang >= 21 on the following code:
Results in: