Using the pattern assignment operator

Having the following code, why does the first assignment not call the operator= pattern in Foo , but the second does? What's going on here? Is there a compiler-generated one for the first assignment, even if a custom template exists?

 #include <iostream> using namespace std; struct UberFoo { }; struct Foo : public UberFoo { template<typename T> void operator=(const T& v) { cout << "const T&" << endl; Set(v); } template<typename T> void operator=(T& v) { cout << "T&" << endl; return Set(v); } virtual void Set(const Foo&) { cout << "Foo::Set(const Foo&)" << endl; } virtual void Set(const UberFoo&) { cout << "Foo::Set(const UberFoo&)" << endl; } }; struct Bar : public Foo { virtual void Set(const Foo&) { cout << "Bar::Set(const Foo&)" << endl; } virtual void Set(const UberFoo&) { cout << "Bar::Set(const UberFoo&)" << endl; } }; int main() { Bar a, b; Foo & pa = a; const Foo& rb = b; const UberFoo & urb = b; cout << "First" << endl; pa = rb; cout << endl << "Second" << endl; pa = urb; return 0; } 
+6
source share
2 answers

The compiler still generates a non-templated operator= , to which the first assignment is bound. In the second assignment, the template operator= is the best candidate (because it does not include any translation), so it is selected.

This can be seen by adding the following to your code:

 Foo& operator=(const Foo&) = delete; 

Or force the correct template call:

 pa.operator=<Foo>(b); 

The standard says (focus):

12.8 Copying and moving class objects, ยง12.8 / 17, p. 271:

An operator-assigned assignment operator of the operator X :: operator = is a non-static function without a class X template with exactly one parameter of type X, X &, const X &, volatile X & or const volatile X &

ยง12.8 / 18, on the same page:

If the class definition does not explicitly declare the copy assignment operator, it is declared implicitly.

+5
source

why does the first assignment not call the template operator = in Foo, but the second does? What's going on here?

In addition to the fact explained by William, the answer to the implicitly generated function of the copy assignment operator, in this case there is also permission to overload. Below are the candidates for the first assignment operator after replacing the argument template, as seen by the compiler:

 Foo& operator=(const Foo&); // implicitly generated void operator=(const Foo&); // template generated 

All things being equal, nontemplate functions are preferable to functional templates. In accordance with C ++ 11 (project N3337), 13.3.3 / 1 (emphasis mine)

Given these definitions, a viable function F1 is defined as a better function than another viable function F2, if for all arguments i, ICSi (F1) is no worse than the transformation scheme than ICSi (F2), and then

- for some argument j, ICSj (F1) is a better conversion sequence than ICSj (F2), or, if not this,

- the context is initialization by user conversion (see 8.5, 13.3.1.5 and 13.3.1.6) and the standard conversion sequence from the return type F1 to the destination type (i.e., the initialization type of the object) is a better conversion sequence than the standard conversion sequence from return type F2 to destination type. [...] or, if not this,

- F1 is a function without a template, and F2 is a specialized function of a template , or, if not this,

- F1 and F2 are specialized function templates, and the function template for F1 is more specialized than the template for F2 in accordance with the partial ordering rules described in 14.5.6.2.

This explains why non-template overload is selected. You can check the same with a little exercise:

 void print(int, int) { std::cout << "int"; } template <typename T> void print(T, T) { std::cout << "T"; } print(1, 2); // prints int print<>(1, 2); // prints T 

As for the second assignment, he sees

 Foo& operator=(const Foo&); // implicitly generated void operator=(const UberFoo&); // template generated 

Here, the generated function template is closer than the implicitly generated function, and therefore it was selected.

+1
source

Source: https://habr.com/ru/post/971011/


All Articles