is_convertible and non-movable types

33 views
Skip to first unread message

David Krauss

unread,
Jul 29, 2015, 4:37:00 AM7/29/15
to std-dis...@isocpp.org
This is ill-formed, so the corresponding is_convertible returns false:

struct immovable {
    immovable( int ) {}
    immovable( immovable && ) = delete;
};

immovable do_() {
    return 42; // Error: need move constructor in absence of copy elision.
}

However, the implicit conversion works, and this is well formed:

immovable do_() {
    return { 42 };
}

The braces don’t enable an explicit conversion, so why shouldn’t the is_convertible trait be defined in terms of the latter function?

dyp

unread,
Jul 29, 2015, 4:46:57 AM7/29/15
to std-dis...@isocpp.org
Implicit convertibility is defined in [conv]p3 as:

An expression e can be implicitly converted to a type T if and only if
the declaration T t=e; is well-formed, for some invented temporary
variable t.

The copy-initialization T t = e; requires either that the type of e is
the same as, or a derived class of T -- or, that T is movable, because a
temporary T is constructed on the rhs and moved (though elided) to the lhs.

So, the definition of `is_convertible` is consistent with the core
language definition of *implicitly convertible*. Also consider:

void foo(immovable) {}

foo(42); // error: immovable is not movable

Changing the trait would require additional checks to test whether or
not you can write code that relies on implicit conversions. Maybe there
should be another more atomic trait, but I think is_convertible is fine
for the purpose of checking whether or not we can write

T t = e;
foo(e);

and so on.

David Krauss

unread,
Jul 29, 2015, 6:02:48 AM7/29/15
to std-dis...@isocpp.org
On 2015–07–29, at 4:46 PM, dyp <dyp...@gmx.net> wrote:

Changing the trait would require additional checks to test whether or
not you can write code that relies on implicit conversions. Maybe there
should be another more atomic trait, but I think is_convertible is fine
for the purpose of checking whether or not we can write

T t = e;
foo(e);

I was thinking along the lines of this, which does work:

void foo(immovable const &) {}
foo( e );

Conditionally-explicit constructors (such as std::pair in the current thread "unordered_map emplace issue”) deduce explicitness by taking the difference of is_convertible and is_constructible, which isn’t quite right.

However, you’re right, it’s better if is_convertible continues to reflect ordinary copy construction syntax.

Ville Voutilainen

unread,
Jul 29, 2015, 6:19:34 AM7/29/15
to std-dis...@isocpp.org
On 29 July 2015 at 12:02, David Krauss <pot...@mac.com> wrote:
> Conditionally-explicit constructors (such as std::pair in the current thread
> "unordered_map emplace issue”) deduce explicitness by taking the difference
> of is_convertible and is_constructible, which isn’t quite right.


Which part of it is wrong?
Reply all
Reply to author
Forward
0 new messages