Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences between std::is_convertible and std::convertible_to (in practice)?

According to en.cppreference.com (from what I can gather):

  • std::is_convertible is a trait class requiring types From & To to be such that a function with return type To that returns a From value can compile.
  • std::convertible_to is a concept requiring types From & To to be as explained above, AND such that an r-value reference of type From can be converted with static_cast<To>.

The requirement imposed by std::is_convertible seems relatively straight-forward. Conversely, the r-value reference casting requirement of std::convertible_to seems oddly specific for such a generic concept that is shown in simple examples for C++20 features.

Being a novice in C++, I could not quite understand some terminology and parts of the supplementary descriptions provided in both webpages and I cannot imagine the exact difference between the requirements of either.

Some inter-related questions:

  • What are the practical implications for types From & To of not only being constrained by std::is_convertible but also by the strange r-value reference casting requirement?
  • What kind of candidate types for From & To are additionally rejected by the r-value reference casting requirement?
  • Why might a programmer want to use either of std::is_convertible or std::convertible_to, instead of the other, as constraints for their function return types or parameter types (aside from just the convenience of concepts)?

A simpler explanation or an example would help. Thank you!

like image 204
Monad Avatar asked Jun 29 '20 17:06

Monad


1 Answers

std::is_convertible<From, To> (the type trait) checks is type From is implicitly convertible to type To.

std::convertible_to<From, To> (the concept) checks that From is both implicitly and explicitly convertible to To. It's rare that this is not the case, such types are ridiculous, but it's nice in generic code to just not have to worry about that case.

One example:

struct From;
struct To {
    explicit To(From) = delete;
};
struct From {
    operator To();
};

static_assert(std::is_convertible_v<From, To>);
static_assert(not std::convertible_to<From, To>);
like image 170
Barry Avatar answered Oct 07 '22 22:10

Barry