[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] Dealing with deleted operator<<() overloads for wide char type
From: |
Greg Chicares |
Subject: |
Re: [lmi] Dealing with deleted operator<<() overloads for wide char types in C++20 |
Date: |
Mon, 1 Mar 2021 21:59:59 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 |
On 2/26/21 12:29 AM, Vadim Zeitlin wrote:
> On Thu, 25 Feb 2021 22:35:34 +0000 Greg Chicares <gchicares@sbcglobal.net>
> wrote:
>
> GC> On 2/25/21 8:55 PM, Vadim Zeitlin wrote:
> GC> [...]
> GC> > [in C++20] we can't insert
> GC> > a char16_t value into the stream any more.
> GC> >
> GC> > There are several ways to solve this, but I wonder if it's even worth
> GC> > solving it at all, or if we could simply remove test_same() calls for
> the
> GC> > char{16,32}_t and wchar_t types in the test? It seems exceedingly
> unlikely
> GC> > that bourn_cast() would be used with any of these types and, in fact, I
> GC> > wonder if we shouldn't just prevent it from being used with them.
> GC>
> GC> I'd like bourn_cast to work in every case where it could possibly make
> GC> any sense--not excluding cases that are valid but seem unlikely--and
> GC> likewise for its unit test.
>
> This is perfectly understandable, but IMO casting chars is exactly a case
> which just doesn't make sense. You wouldn't, presumably, attempt to make
> bourn_cast() work with strings, so why would you ever want to use it with
> char{16,32}_t which can be exactly the same thing as UTF-8-encoded
> multi-byte string?
I'm not sure I follow. As you know, C++20 (N4861) says [6.8.1]:
| 11. Types bool, char, wchar_t, char8_t, char16_t, char32_t, and
| the signed and unsigned integer types are collectively called
| integral types. A synonym for integral type is integer type.
| 12. There are three floating-point types: float, double, and
| long double. ... Integral and floating-point types are
| collectively called arithmetic types.
Shouldn't the domain of bourn_cast<T,U> be all arithmetic types {T,U}?
I don't even know what these goofy types are supposed to be: maybe
UCS-2 and UCS-4, or something like that. But I don't see why the
motivation for their existence would need to be considered here:
they're arithmetic types, and isn't that all I need to know?
> GC> I'd be inclined to replace
> GC> INVOKE_BOOST_TEST_EQUAL(x, y, file, line);
> GC> (only where it is actually problematic) with
> GC> INVOKE_BOOST_TEST(x == y, file, line);
> GC> (I haven't tested that, but I'm sure something like it would work.
> GC> The -"_EQUAL" macros are handy because on failure they print the two
> GC> values that are unexpectedly unequal; but that handiness isn't very
> GC> important for debugged code.)
> GC>
> GC> Do you see a better way, or should I just make it so?
>
> I indeed think this would work, but doing it just for these types would be
> a bit messy because we use it in a template function, so it'd require an
> "if constexpr" (which is, of course, only a bit messy, compared to
> SFINAE-level mess we'd have to use with pre-C++17 C++).
I did something much simpler in commit e89831e23. IOW, here:
> GC> I'd be inclined to replace
> GC> INVOKE_BOOST_TEST_EQUAL(x, y, file, line);
> GC> (only where it is actually problematic) with
> GC> INVOKE_BOOST_TEST(x == y, file, line);
what does the (ambiguous) "actually problematic" mean? I
intended "on any line flagged in a compiler diagnostic,
regardless of what remote line it was invoked from": thus,
"potentially problematic" might have been a better phrase.
The tests for equality are preserved. All that's lost is
the incidental printing of their (unequal) values.
But maybe I misunderstand something. From my POV above,
integral types are integral types, and that's that, so
making some of them streamable and others not is lunacy.
> It would also still leave us with the same problem in any other place
> where we might use BOOST_TEST_EQUAL[*] with these types.
But AFAICS that no longer occurs anywhere, since e89831e23.
> So I was rather
> thinking of implementing a complete solution for this by defining a
> template lmi_test::to_string() function
Nothing new to invent:
template<typename T>
lmi_test::to_string(T t)
{return value_cast<std::string>(t);}
Would you be in favor of a change such as the following?
#define LMI_ASSERT_EQUAL(observed,expected) \
LMI_ASSERT_WITH_MSG \
((observed) == (expected) \
- ,"expected " << (expected) << " vs observed " << (observed) \
+ , "expected " << value_cast<std::string>(expected) "\
+ << " vs observed " << value_cast<std::string>(observed) \
)
I'd be somewhat opposed because that introduces heavyweight
header "value_cast.hpp" into lightweight "assert_lmi.hpp",
compounding the fragility of assertion code that already
uses heavyweight std:: stuff that can throw exceptions.
We would be able to consider using std::to_string(), except
that they defined its domain to include certain integral
types but exclude others.
> But my preference would still be to just forbid using bourn_cast() with
> the wide char types as I remain convinced that this is an operation which
> simply never makes sense.
Again, maybe I'm missing something, but to me:
- arithmetic types should be streamable
- the real error is that types like char16_t and char32_t exist
> [*] We really, really ought to rename these macros to LMI_TEST_EQUAL() or
> something else not starting with BOOST_, pretending that they come from
> Boost is still confusing, even after all these years, and just imagine
> how puzzling it is to anybody new to lmi code base (I didn't have to
> imagine this when I saw Ilya being completely misled by their names
> relatively recently).
Okay, I'll do that.
- Re: [lmi] Dealing with deleted operator<<() overloads for wide char types in C++20,
Greg Chicares <=