Why can I prevent implicit conversions for primitives but not user-defined types?

High-integrity C ++ standards assume that rvalue arguments to functions can be removed, which prevents implicit conversions.

http://www.codingstandard.com/rule/8-3-4-define-delete-functions-with-parameters-of-type-rvalue-reference-to-const/

I've found that the behavior for primitives and custom types is very different.

struct A { };

struct B { B(const A& ) {} };

template <class T>
void foo(const T&&) = delete;  // 1 - deleted rvalue overload. const intentional.

void foo(B) {}                 // 2

void foo(int) {}               // 3

int main(int argc, char* argv[])
{
  A a;
  foo(a);   // This resolves to 2
  foo(3.3); // This resolves to 1
  foo(2);   // This resolves to 3 (as expected).
}       

      

Why does remote rvalue overload prevent implicit conversion to int, but not from one user-defined type to another?

+1


source to share


3 answers


There is no processing difference in your code between custom types and primitive types. The difference between the behavior of these two lines:

foo(a);
foo(3.3);

      



is what a

is an lvalue and 3.3

is an r-value. The rvalue argument matches your overload 1

(which only accepts rvalues), the lvalue argument doesn't matter.

If you try to call foo<A>

with an rvalue argument it will also match 1

and fail, eg. foo(A{});

...

+1


source


The high integrity C ++ standards show that rvalue arguments to a function can be removed, which prevents implicit conversions.

No, only the link overload forwarder disables ICS (Implicit Sequence) for all other overloads in the overload set. Make a forwarding link and see ICS disabled (Coliru Link)

template <class T>
void foo(const T&&) = delete;  // introduces a qualification match

      



The above code adds qualification matching to the overload. So ICS is still in the game.

Why foo(3.3)

it failed, since 3.3

is a prvalue of type double

which would better match rvalue overload than conversion to int

. Because qualification fit is rated better than conversion fit

+2


source


There are 3 possible overloads

  • 1 is viable.
  • 2 viable
  • 3 not

2 is the best match (pattern (not an exact match) vs. normal method (with one user specifying the transformation)).

You can look at http://en.cppreference.com/w/cpp/language/overload_resolution to see the full set of rules required

+1


source







All Articles