[Bug libstdc++/69191] Wrong equality comparison between error_code and error_condition + segfault

2016-08-04 Thread kristian.spangsege at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69191

Kristian Spangsege  changed:

   What|Removed |Added

 CC||kristian.spangsege at gmail 
dot co
   ||m

--- Comment #13 from Kristian Spangsege  
---
I've now run into this problem too, and it seems to be general, not just
limited to Ubuntu.

There is the code that I compile:

#include 
#include 
#include 

int main()
{
std::error_code ec(EDOM, std::system_category());
bool b = (ec == std::errc::argument_out_of_domain);
std::cout << b << "\n";
}

I expect it to write `1`, not `0`.

I get the expected result with Clang on OS X. I get the wrong result with

 - GCC 6.1.1 on Fedora 24, which links against libstdc++.so.6.0.22
 - GCC 5.4.0 on Linux Mint 18 (Ubuntu 14.04), which links against
libstdc++.so.6.0.21
 - GCC 4.9.3 on Linux Mint 17.1 (Ubuntu 16.04), which links against
libstdc++.so.6.0.22

It therefore seems to me that this is really a bug in libstdc++.

[Bug libstdc++/86292] New: Missing exception safety when constructing vector from input iterator pair

2018-06-23 Thread kristian.spangsege at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86292

Bug ID: 86292
   Summary: Missing exception safety when constructing vector from
input iterator pair
   Product: gcc
   Version: 8.0.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: kristian.spangsege at gmail dot com
  Target Milestone: ---

Created attachment 44316
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44316&action=edit
Code to trigger the bug

When constructing a `std::vector` from a pair of input iterators
(`std::input_iterator_tag`), and the copy constructor for the value type
throws, already constructed copies will never be destroyed. I.e., the mentioned
vector constructor is not exception safe under these circumstances.

See the attached code for a way to trigger and reveal the problem.

The expectation is that it should output `0` (no instances of `X` remain at
exit), but it outputs `1`, meaning that one `X` object was leaked.

I tried this with GCC version 8.0.1 and 5.5.0 on Linux Mint 18.1.

[Bug libstdc++/86295] New: Missing exception safety when inserting range into vector

2018-06-24 Thread kristian.spangsege at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86295

Bug ID: 86295
   Summary: Missing exception safety when inserting range into
vector
   Product: gcc
   Version: 8.0.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: kristian.spangsege at gmail dot com
  Target Milestone: ---

When inserting a range into a `std::vector`, and the copy, or move constructor
for the value type throws at an unfortunate time, some constructed objects of
the value type will never be destroyed.

More specifically, the version of `std::vector::_M_range_insert()`, that is for
forward iterators, has calls to `std::__uninitialized_copy_a()` and
`std::__uninitialized_move_a()` at various places. If I understand correctly,
these functions construct a number of new objects of the value type. After each
such call, the logical size of the vector is then increased by the number of
new objects.

The problem occurs when either `std::__uninitialized_copy_a()` or
`std::__uninitialized_move_a()` throws due to throwing from the copy or move
constructor of the value type. In this case, the logical size of the vector
remains at its prior value, which means that if any objects were created, they
will be forgotten about (leaked).

As far as I can see, a solution would be to the carry out these copy and move
operations one value at a time, and update the logical size after each step.

I am referring to the version of libstdc++ that comes with GCC 8.0.1 here.

[Bug libstdc++/86295] Missing exception safety when inserting range into vector

2018-06-25 Thread kristian.spangsege at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86295

--- Comment #2 from Kristian Spangsege  ---
Oh, I missed that crucial fact. Sorry. We can close this as invalid then.

On Mon, Jun 25, 2018 at 3:35 PM, redi at gcc dot gnu.org <
gcc-bugzi...@gcc.gnu.org> wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86295
>
> --- Comment #1 from Jonathan Wakely  ---
> (In reply to Kristian Spangsege from comment #0)
> > The problem occurs when either `std::__uninitialized_copy_a()` or
> > `std::__uninitialized_move_a()` throws due to throwing from the copy or
> move
> > constructor of the value type. In this case, the logical size of the
> vector
> > remains at its prior value, which means that if any objects were created,
> > they will be forgotten about (leaked).
>
> Do you have a testcase?
>
> If an exception occurs in __uninitialized_copy_a and __uninitialized_move_a
> they will destroy any objects they created, so I don't see how they can
> leak.
>
> --
> You are receiving this mail because:
> You reported the bug.
>

[Bug c++/56421] New: Non-matching overload produces template substitution error

2013-02-21 Thread kristian.spangsege at gmail dot com

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56421

 Bug #: 56421
   Summary: Non-matching overload produces template substitution
error
Classification: Unclassified
   Product: gcc
   Version: 4.7.2
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: kristian.spangs...@gmail.com


template struct Foo {
  typedef typename S::type type;
};

template void foo();
template typename Foo::type foo(int);

int main()
{
  foo();
}


Produces the following error in both gcc-4.7.2 and gcc-4.6.3:

$ g++ -c t.cpp
t.cpp: In instantiation of ‘struct Foo’:
t.cpp:6:41:   required by substitution of ‘template typename Foo::type
foo(int) [with S = int]’
t.cpp:10:12:   required from here
t.cpp:2:28: error: ‘int’ is not a class, struct, or union type


Clang accepts it as valid.


Note: No errors are reported by GCC if we change line 6 from

  template typename Foo::type foo(int);

to

  template typename S::type foo(int);


[Bug c++/56421] Non-matching overload produces template substitution error

2013-02-22 Thread kristian.spangsege at gmail dot com

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56421

--- Comment #5 from Kristian Spangsege  
2013-02-22 18:04:41 UTC ---
(In reply to comment #4)
> I think 13.3 [over.match] ¶2 and 13.3.1 [over.match.funcs] ¶7  say the 
> function
> template specialization must be generated before the number of arguments is
> checked to see if the candidate function is viable.

Not so.

Function templates must not be instantiated unless the number of arguments
match.

[C++11: 13.3/2]:

- First, a subset of the candidate functions (those that have the proper number
of arguments and meet certain other conditions) is selected to form a set of
viable functions (13.3.2).

- Then the best viable function is selected based on the implicit conversion
sequences (13.3.3.1) needed to match each argument to the corresponding
parameter of each viable function.

[C++11: 13.3.1/7]:

In each case where a candidate is a function template, candidate function
template specializations are generated using template argument deduction
(14.8.3, 14.8.2). Those candidates are then handled as candidate functions in
the usual way.


[Bug c++/56421] Non-matching overload produces template substitution error

2013-02-22 Thread kristian.spangsege at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56421



--- Comment #9 from Kristian Spangsege  
2013-02-22 23:09:59 UTC ---

Daniell, would you do me the favour of explaining exactly why you think my

example is ill-formed?


[Bug c++/56421] Non-matching overload produces template substitution error

2013-02-22 Thread kristian.spangsege at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56421



--- Comment #10 from Kristian Spangsege  
2013-02-22 23:11:13 UTC ---

Daniel - excuse me :-)


[Bug c++/56421] Non-matching overload produces template substitution error

2013-02-22 Thread kristian.spangsege at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56421



--- Comment #12 from Kristian Spangsege  
2013-02-22 23:38:47 UTC ---

Yes, so far so good, but where does the standard say that if synthesis fails

for a particular candidate function template declaration, during overload

resolution, then the code is ill-formed?


[Bug c++/56421] Non-matching overload produces template substitution error

2013-02-22 Thread kristian.spangsege at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56421



--- Comment #13 from Kristian Spangsege  
2013-02-22 23:46:04 UTC ---

Jonathan,



"The complete set" is the set *before* the number of arguments is considered to

find the viable subset. To synthesize the declaration Foo::type must be

known, and that type results in an error.



Why then is the following accepted (replaced "Foo::type" with "S::type"):



template struct Foo {

  typedef typename S::type type;

};



template void foo();

template typename S::type foo(int);



int main()

{

  foo();

}


[Bug c++/56421] Non-matching overload produces template substitution error

2013-02-22 Thread kristian.spangsege at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56421



--- Comment #14 from Kristian Spangsege  
2013-02-23 00:02:55 UTC ---

Jonathan, you say that:



"Foo::type exists unconditionally, so SFINAE doesn't apply.

The invalid type is not in the immediate context of the substitution."



Could you point me to the relevant section(s) in the standard?


[Bug c++/56421] Non-matching overload produces template substitution error

2013-02-22 Thread kristian.spangsege at gmail dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56421



--- Comment #17 from Kristian Spangsege  
2013-02-23 01:35:02 UTC ---

Dude, you are insulting my ego! :-)



Anyway, thanks for pointing me to [temp.deduct]/8. SFINAE certainly does not

apply in my example.


[Bug c++/53102] New: Misplaced 'typename' gives access to private type

2012-04-24 Thread kristian.spangsege at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53102

 Bug #: 53102
   Summary: Misplaced 'typename' gives access to private type
Classification: Unclassified
   Product: gcc
   Version: 4.6.3
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: kristian.spangs...@gmail.com


Here 'typename' is used outside a template, in which case it apparently
invalidly gives access to A::type.


class A {
private:
  typedef int type;
};

class B {
public:
  typedef typename A::type type;
};


int main()
{
  B::type v = 8;
  return v;
}


[Bug c++/50033] New: Failing ADL for template-id function call

2011-08-09 Thread kristian.spangsege at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50033

 Bug #: 50033
   Summary: Failing ADL for template-id function call
Classification: Unclassified
   Product: gcc
   Version: 4.4.3
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: kristian.spangs...@gmail.com


Unexpected failure to compile the following sample:

namespace N
{
  struct A {};

  template void func(A const &, B const &) {}
}

int main()
{
  N::A a;
  func(a, 7);
  func(a, 7);
  return 0;
}

The first call to func() without the template argument works fine.

The second one fails because 'func' cannot be found.

Is this really in agreement with the standard, or is it a bug in GCC?

I saw this with GCC version 4.4.3.


Regards,
Kristian Spangsege


[Bug libstdc++/58341] Doc conflicts with standard on forbidden range of `result` in copy_backward()

2013-09-06 Thread kristian.spangsege at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58341

--- Comment #2 from Kristian Spangsege  ---
And more importantly, here:
http://cplusplus.github.io/LWG/lwg-defects.html#1206


[Bug libstdc++/58341] Doc conflicts with standard on forbidden range of `result` in copy_backward()

2013-09-06 Thread kristian.spangsege at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58341

--- Comment #1 from Kristian Spangsege  ---
Important related information here:
http://en.cppreference.com/w/Talk:cpp/algorithm/copy_backward


[Bug libstdc++/58341] New: Doc conflicts with standard on forbidden range of `result` in copy_backward()

2013-09-06 Thread kristian.spangsege at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58341

Bug ID: 58341
   Summary: Doc conflicts with standard on forbidden range of
`result` in copy_backward()
   Product: gcc
   Version: 4.8.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: kristian.spangsege at gmail dot com

The documentation of copy_backward() in  conflicts with
the C++ standard on the forbidden range of `result`.

The documentation states that `result` must not be within the range [`first`,
`last`). The standard instead requires that `result` is not within the range
(`first`, `last`].

It is probably just a typo.

See C++11 (2011-09-01) section 25.3.1/13.


[Bug libstdc++/60326] New: Incorrect type from std::make_unsigned

2014-02-23 Thread kristian.spangsege at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60326

Bug ID: 60326
   Summary: Incorrect type from std::make_unsigned
   Product: gcc
   Version: 4.8.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: kristian.spangsege at gmail dot com

The `std::make_signed` and `std::make_unsigned` templates appear to be
incorrectly implemented in GCC 4.8.1.

In particular, both `std::make_signed::type` and
`std::make_unsigned::type` produces the type `wchar_t`.

I don't claim to know what the right behaviour is, but it seems wrong, what is
currently done.

Clang 3.4 with `libc++` does this on x86_64:

std::make_unsigned::type --> int 
std::make_unsigned::type --> unsigned

which seems more reasonable.

The most relevant section in the C++11 standard appears to be 20.9.7.3
[meta.trans.sign].


[Bug libstdc++/60326] Incorrect type from std::make_unsigned

2014-02-23 Thread kristian.spangsege at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60326

--- Comment #1 from Kristian Spangsege  ---
Oops, should have been:

Clang 3.4 with `libc++` does this on x86_64:

std::make_signed::type --> int 
std::make_unsigned::type --> unsigned


[Bug libstdc++/37475] [DR 382] codecvt::do_in/do_out functions return "ok" when the output sequence has zero length

2024-06-11 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37475

--- Comment #6 from Kristian Spangsege  ---
Created attachment 58405
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58405&action=edit
Test whether bug still exists in GCC 14.0.1

[Bug libstdc++/37475] [DR 382] codecvt::do_in/do_out functions return "ok" when the output sequence has zero length

2024-06-11 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37475

--- Comment #7 from Kristian Spangsege  ---
This bug still exists in GCC 14.0.1. This was tested with the attacked
test_2.cpp. The actual result is `ok`, but it should have been `partial`.

Curiously, this bug does not occur when using the Cygwin or MinGW versions of
GCC. In these cases, the result is `partial` as it should be. I assume this is
because on Cygwin and MinGW, libstdc++ uses a generic locale implementation
that is different from the one ordinarily used on Linux.

[Bug libstdc++/37475] codecvt::do_in/do_out functions return "ok" when the output sequence has zero length

2024-06-11 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37475

--- Comment #12 from Kristian Spangsege  
---
These changes look good to me.

A couple of points:
* Should the `else`s still be there now that the preceding branches terminate
with `break`?
* `do_out()` has the same problem as `do_in()`.
* If there is already testing of `codecvt`, should a test be added for the
"empty output" case?
* This could break code that expects the incorrect behavior.

[Bug libstdc++/37475] [DR 382] codecvt::do_in/do_out functions return "ok" when the output sequence has zero length

2021-02-08 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37475

Kristian Spangsege  changed:

   What|Removed |Added

 CC||kristian.spangsege at gmail 
dot co
   ||m

--- Comment #5 from Kristian Spangsege  ---
This bug still exists in GCC 10.2, while libc++ (clang) appears to do the right
thing.

Specifically, when passing a nonzero amount of data (from_end > from) to
std::codecvt::out(), but an empty output buffer (to_end == to), the return
value is "ok". According to the C++ standard (C++17), the correct return value
is "partial".

This appears to happen regardless of locale. In particular, it happens in the C
locale.

As far as I can tell, http://cplusplus.github.io/LWG/lwg-closed.html#382 is not
relevant here, because the current standard text is clear (C++17), and
http://cplusplus.github.io/LWG/lwg-closed.html#382 has status NAD, which I
assume means "not a defect".

Jonathan, let me know if I am missing something.

[Bug libstdc++/97311] New: Bug in std::seed_seq::generate() when integer type has more than 32 bits

2020-10-06 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97311

Bug ID: 97311
   Summary: Bug in std::seed_seq::generate() when integer type has
more than 32 bits
   Product: gcc
   Version: 10.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: kristian.spangsege at gmail dot com
  Target Milestone: ---

As far as I can tell, std::seed_seq::generate() has a bug when _Type has more
than 32 bits.

The problem is that the following two additions can produce values greater
than, or equal to 2**32:

__begin[(__k + __p) % __n] += __r1;
__begin[(__k + __q) % __n] += __r2;

According to C++17 standard text, all operations must be performed modulo
2**32, so no generated value can be greater than, or equal to 2**32.

It seems that a possible fix would be to change those two lines to something
like this:

__begin[(__k + __p) % __n] = __detail::__mod<_Type, __detail::_Shift<_Type,
32>::__value>(__begin[(__k + __p) % __n] + __r1));
__begin[(__k + __q) % __n] = __detail::__mod<_Type, __detail::_Shift<_Type,
32>::__value>(__begin[(__k + __q) % __n] + __r2));

[Bug libstdc++/97311] Bug in std::seed_seq::generate() when integer type has more than 32 bits

2020-10-07 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97311

--- Comment #3 from Kristian Spangsege  ---
I would recommend not locking arithmetic to std::uint32_t, and instead working
with std::uint_fast32_t, because I can imaging a platform (current or future)
where 32-bit arithmetic is slower that 64-bit arithmetic. As a bonus, the code
will work on platforms that do not have std::uint32_t.

[Bug c++/113063] New: Strange linker error in special case involving local class with defaulted spaceship operator and static assert

2023-12-18 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113063

Bug ID: 113063
   Summary: Strange linker error in special case involving local
class with defaulted spaceship operator and static
assert
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: kristian.spangsege at gmail dot com
  Target Milestone: ---

With the latest GCC (13.2) and also with GCC 11.4, the following C++ code
triggers a strange linker error:


#include 

int main()
{
struct X {
auto operator<=>(const X&) const = default;
};
X x;
static_assert(noexcept(x < x));
static_cast(x < x);
}


Godbolt: https://godbolt.org/z/PfPfznT6Y


The linker error is this:

/usr/bin/ld: /tmp/ccsnSU59.o: in function `main::X::operator<=>(X const&)
const':
t.cpp:(.text+0x31): undefined reference to
`std::strong_ordering::strong_ordering(std::strong_ordering const&)'


It seems to be a bug that is triggered by the presence of the static assertion,
but only when the it occurs before the actual invocation of the less-than
comparison operation. Also, if the local class (`X`) is moved out of `main()`,
the problem goes away.

[Bug c++/113063] Strange linker error in special case involving local class with defaulted spaceship operator and static assert

2023-12-18 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113063

--- Comment #1 from Kristian Spangsege  ---
By the way, and as expected, this problem does not exist in Clang.

[Bug c++/113063] Strange linker error in special case involving local class with defaulted spaceship operator and static assert

2023-12-20 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113063

--- Comment #6 from Kristian Spangsege  ---
Thanks for fixing it. Should it be back-ported to earlier GCC versions? From my
point of view, as far back as GCC 11 would be nice.

[Bug libstdc++/37475] codecvt::do_in/do_out functions return "ok" when the output sequence has zero length

2024-06-17 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37475

--- Comment #14 from Kristian Spangsege  
---
Is the underscore intended before `Guard` in `explicit _Guard(__c_locale) { }`
for the GLIBC <= 2.2 case?

Besides that, the full patch looks correct to me.

[Bug c++/115524] New: Cygwin: Space character categorized as non-printable by std::ctype

2024-06-17 Thread kristian.spangsege at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115524

Bug ID: 115524
   Summary: Cygwin: Space character categorized as non-printable
by std::ctype
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: kristian.spangsege at gmail dot com
  Target Milestone: ---

Created attachment 58451
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58451&action=edit
test.cpp Demonstrate the bug

On Cygwin, a space character is reported as non-printable by
`std::ctype` in the "C" locale (the only locale supported by
libstdc+++ on Cygwin). In other words, the following expression evaluates to
`false`:

ctype.is(std::ctype_base::print, ctype.widen(' '))

where `ctype` is obtained by `std::use_facet>(loc)` and
`loc` is the "C" locale.

It should have been evaluated to `true` because a space character is required
by the C++ standard to be categorized as printable (the defining distinction
between a printable and a graphical character is that space is printable but
not graphical).

Also, the space character is reported as printable by `std::iswprint(int ch)`.
So it seems like the problem is specific to `libstdc++`.

Also, the non-wide space character is reported as printable, i.e,
`std::use_facet>(loc)::is(std::ctype_base::print, ' ')` is
`true`.

Also, `ctype.is(std::ctype_base::print, ctype.widen(' '))` is `true` with
MinGW, with GCC on Linux, and with Visual Studio.

The problem can be demonstrated with the code below (attached as `test.cpp`) in
regular Cygwin (https://cygwin.com/install.html) using GCC 12.3.1 and in the
Cygwin environment of MSYS2 (https://www.msys2.org/) using GCC 13.2.0:

#include 
#include 
#include 
#include 

int main()
{
using facet_type = std::ctype;
std::locale loc;
const auto& ctype = std::use_facet(loc);
wchar_t ch = ctype.widen(' ');
std::cout << ctype.is(ctype.print, ch) << "\n";
std::cout << (std::iswprint(std::char_traits::to_int_type(ch)) !=
0) << "\n";
}