Yesterday in the course of answering someone else's question I was
surprised to discover that gcc 4.7.2 <type_traits>
contained the trait
template std::is_explicitly_convertible<From,To>
, defined
as the inverse of std::is_constructible_convertible<To,From>
:
/// is_explicitly_convertible
template<typename _From, typename _To>
struct is_explicitly_convertible
: public is_constructible<_To, _From>
{ };
Searching for paper-trail, I then discovered that this trait ought not to have been there. A bug was raised against its inclusion in that version of the C++11 Standard Library and it was removed in gcc 4.8.0.
That bug report pointed out that std::is_explicitly_convertible
(having
been mandated in earlier drafts of the C++0x Standard), was removed from the
draft Standard by N3047
in 2010.
N3047 explains this about-turn:
The remaining question is, in which way the also affected
is_explicitly_convertible
trait should be repaired. The basic choices are:
- Fix
is_explicitly_convertible
by returning to the currentstatic_cast
expression, no longer makingis_explicitly_convertible
dependent onis_constructible
.- Remove
is_explicitly_convertible
from the standard.The first choice was considered, but it turned out that there exist quite different understandings of what "explicitly convertible" should actually mean. While some believe that
static_cast
correctly expresses this, others believed that the fixedis_constructible
would provide a better meaning foris_explicitly_convertible
as well. Therefore this paper recommends to remove theis_explicitly_convertible
from the working draft. This should do no harm now, because nothing depends on that special definition yet. And if it turns out, that the trait would still be useful, it could be added in another revision of the standard.
This explanation seems to imply that the parties to the disagreement knew of
cases in which, for an expression from
of type From
, static_cast<To>(from)
would
compile while To to{from};
would not; or vice versa.
Are there such cases?
If not, can anyone authoritatively (not speculatively, please) explain
the distinction between static_castibility of From
to To
and
constructibility of To
from From
that was in play here?
First, some test code. TestA
is your explicit construction, and TestB
is your explicit static_cast
ing:
template<typename To, typename From>
To TestA(From from) {
To to{from};
return to;
}
template<typename To, typename From>
To TestB(From from) {
return static_cast<To>(from);
}
static_cast
allows downcasting in an object heirarchy, while explicit construction does not:
struct Base {};
struct Derived:Base {};
int main() {
Base* b;
// TestA<Derived*>(b); -- fails to compile
TestB<Derived*>(b);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With