is_convertible
Section: 21 [meta] Status: Resolved Submitter: Daniel Krügler Opened: 2011-03-03 Last modified: 2020-09-06
Priority: Not Prioritized
View other active issues in [meta].
View all other issues in [meta].
View all issues with Resolved status.
Discussion:
When n3142 was suggested, it concentrated on constructions, assignments, and destructions, but overlooked to complement the single remaining compiler-support trait
template <class From, class To> struct is_convertible;
with the no-throw and triviality related aspects as it had been done with the other expression-based traits. Specifically, the current specification misses to add the following traits:
template <class From, class To> struct is_nothrow_convertible; template <class From, class To> struct is_trivially_convertible;
In particular the lack of is_nothrow_convertible
is severely restricting. This
was recently recognized when the proposal for decay_copy
was prepared by
n3255.
There does not exist a portable means to define the correct conditional noexcept
specification for the decay_copy
function template, which is declared as:
template <class T> typename decay<T>::type decay_copy(T&& v) noexcept(???);
The semantics of decay_copy
bases on an implicit conversion which again
influences the overload set of functions that are viable here. In most circumstances
this will have the same effect as comparing against the trait
std::is_nothrow_move_constructible
, but there is no guarantee for that being
the right answer. It is possible to construct examples, where this would lead
to the false result, e.g.
struct S { S(const S&) noexcept(false); template<class T> explicit S(T&&) noexcept(true); };
std::is_nothrow_move_constructible
will properly honor the explicit template
constructor because of the direct-initialization context which is part of the
std::is_constructible
definition and will in this case select it, such that
std::is_nothrow_move_constructible<S>::value == true
, but if we had
the traits is_nothrow_convertible
, is_nothrow_convertible<S, S>::value
would evaluate to false
, because it would use the copy-initialization context
that is part of the is_convertible
definition, excluding any explicit
constructors and giving the opposite result.
The decay_copy
example is surely not one of the most convincing examples, but
is_nothrow_convertible
has several use-cases, and can e.g. be used to express
whether calling the following implicit conversion function could throw an exception or not:
template<class T, class U> T implicit_cast(U&& u) noexcept(is_nothrow_convertible<U, T>::value) { return std::forward<U>(u); }
Therefore I suggest to add the missing trait is_nothrow_convertible
and for
completeness also the missing trait is_trivially_convertible
to 21 [meta].
[2011-03-24 Madrid meeting]
Daniel K: This is a new feature so out of scope.
Pablo: Any objections to moving 2040 to Open? No objections.[Bloomington, 2011]
Move to NAD Future, this would be an extension to existing functionality.
[LEWG, Kona 2017]
Fallen through the cracks since 2011, but we should discuss it. Alisdair points out that triviality is
about replacing operations with memcpy
, so be sure this is false for int
->float
.
[Rapperswil, 2018]
Resolved by the adoption of p0758r1.
Proposed resolution:
Ammend the following declarations to the header <type_traits>
synopsis
in 21.3.3 [meta.type.synop]:
namespace std { … // 20.9.6, type relations: template <class T, class U> struct is_same; template <class Base, class Derived> struct is_base_of; template <class From, class To> struct is_convertible; template <class From, class To> struct is_trivially_convertible; template <class From, class To> struct is_nothrow_convertible; … }
Modify Table 51 — "Type relationship predicates" as indicated. The removal of the
remaining traces of the trait is_explicitly_convertible
is an editorial
step, it was removed by n3047:
Table 51 — Type relationship predicates Template Condition Comments … template <class From, class To>
struct is_convertible;see below From
andTo
shall be complete
types, arrays of unknown bound, or
(possibly cv-qualified)void
types.template <class From, class To>
struct is_explicitly_convertible;is_constructible<To, From>::value
a synonym for a two-argument
version ofis_constructible
.
An implementation may define it
as an alias template.template <class From, class To>
struct is_trivially_convertible;is_convertible<From,
is
To>::valuetrue
and the
conversion, as defined by
is_convertible
, is known
to call no operation that is
not trivial ([basic.types], [special]).From
andTo
shall be complete
types, arrays of unknown bound,
or (possibly cv-qualified)void
types.template <class From, class To>
struct is_nothrow_convertible;is_convertible<From,
is
To>::valuetrue
and the
conversion, as defined by
is_convertible
, is known
not to throw any
exceptions ([expr.unary.noexcept]).From
andTo
shall be complete
types, arrays of unknown bound,
or (possibly cv-qualified)void
types.…