0

[First of First: Vs2019 on Windows10, only C++11 supported]

I've got confused on template copy assignment function like: enter image description here

I found the specilization version is not working, why it is not equal to copy assignment function? isn't that template function will be "extended" like macro?

Let's add a move constructor like this: enter image description here

I know that a userd-declared move constructor will set the implicit copy assignment function to delete. if the template copy assignment function is not a "REAL" copy assignment function, then why the compiler says:

error C2280: 'TestClass &TestClass::operator =(const TestClass &)': attempting to reference a deleted function
message : compiler has generated 'TestClass::operator =' here
message : 'TestClass &TestClass::operator =(const TestClass &)': function was implicitly deleted because 'TestClass' has a user-defined move constructor

So, How does compiler see on the template copy assignment function? To be clear: If template-assign-operator function is not identical to copy-assign operator, why the compiler reminds me 'TestClass &TestClass::operator =(const TestClass &)': function was implicitly deleted

Thanks in advance!

I expect the specilization version of template copy assignment function to be identical to copy assignment function.

Full test code here:

class TestClass
{
    public:
    TestClass() {};
    ~TestClass() {};
    // If the template function is not identical to copy assignment function
    // why the compiler reports error:"function was implicitly deleted because 'TestClass' has a user-defined move constructor"
    TestClass(TestClass&& rhs)
    {

    }

    template <typename T>
    TestClass& operator = (const T& rhs)
    {
        return *this;
    }

    // Why this is not identical to copy assignment function?
    template<>
    TestClass& operator = (const TestClass& rhs)
    {
        return *this;
    }
};

int main()
{
    TestClass A;
    TestClass B;
    B = A;
}
Louis
  • 1
  • 1
  • 2
    We require all code to be in the question itself as text, so we're able to run it ourselves. – HolyBlackCat Jun 25 '23 at 12:19
  • A function template is never a copy-assignment operator; meaning, its presence doesn't suppress the implicitly declared one. Then, a non-template (implicitly declared) function is preferred over the template by overload resolution. Note that functions declared deleted nevertheless participate in overload resolution; if such a function is chosen, the program is ill-formed. What do you mean, "omitted in the first case"? Try printing something in your template specialization; I predict it doesn't actually get called. – Igor Tandetnik Jun 25 '23 at 14:54
  • I've upload the simple test code, thanks :) @HolyBlackCat – Louis Jun 25 '23 at 15:27
  • @IgorTandetnik Thanks for explaination. Now I see template function is never a copy-assignment operator, but why? because after template-instantiated, it should be completely same to the copy-assignment operator. "omitted in the first case" means: if template operator = function is not copy-assignment function, then why it has an error to remind me "function was implicitly deleted" after I add a move-constructor? – Louis Jun 25 '23 at 15:32
  • Why? Because the C++ standard says so. What were the motivations of its authors when they designed this rule, I don't know. – Igor Tandetnik Jun 25 '23 at 17:46
  • In both cases, there's an implicitly declared copy assignment. When there's no user-declared move assignment, this copy assignment is also implicitly defined to perform memberwise copy. `B = A;` calls this assignment. When you add move assignment operator, copy assignment is implicitly declared as deleted. `B = A;` still ends up calling it, whereupon the program is ill-formed. – Igor Tandetnik Jun 25 '23 at 17:47
  • Thanks for the answer, it seems the template function "template<> TestClass& operator = (const TestClass& rhs) " will never been seen by the compiler. is that correct? @IgorTandetnik – Louis Jun 26 '23 at 02:06
  • You could call it explicitly if you were so inclined, as in `B.operator=<>(A);` But indeed, it would never be picked by overload resolution for a plain `B=A;` – Igor Tandetnik Jun 26 '23 at 02:25

0 Answers0