What's the exact semantics of deleted member functions in C++11?

后端 未结 2 1222
夕颜
夕颜 2020-12-08 02:29
struct A
{
    A();

    A(const A&);
    A& operator =(const A&);

    A(A&&) = delete;
    A& operator =(A&&) = delete;
};

struct          


        
相关标签:
2条回答
  • 2020-12-08 02:32

    When you =delete a function, you actually are deleting its definition.

    8.4.3 Deleted definitions [dcl.fct.def.delete]

    1 A function definition of the form:

    attribute-specifier-seqopt decl-specifier-seqopt declarator = delete ;

    is called a deleted definition. A function with a deleted definition is also called a deleted function.

    But by doing so, you are also declaring that function. Quoting from the standard [1]:

    4 A deleted function is implicitly inline. [ Note: The one-definition rule (3.2) applies to deleted definitions. —end note ] A deleted definition of a function shall be the first declaration of the function [...]

    And so by doing a = A(), the compiler actually resolves to A::operator=(A&&) because it has been declared (not A::operator(const A&), because A&& is "more binding" to r-values). However with its definition being deleted, the line is ill-formed.

    2 A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.


    [1] The tone of the emphasized sentence here is actually imperative. The standard directs that declaring a function =deleted must first appear before other declarations of it. But still, it supports the fact that deleting a function also declares the function.

    0 讨论(0)
  • 2020-12-08 02:33
    a = A(); // error C2280
    

    The expression on the right is a temporary which means it will look for operator=(A&&) and sees it is deleted. Hence the error. There is no further search.

    =delete does not mean "don't use me, instead use next best one". It rather means, "don't use me when you need me — instead be alone in the wild."

    Here is another example. If I want the instances of my class X to be created with only long and no other type (even if it converts into long!), then I would declare class X as:

    struct X
    {
         X(long arg); //ONLY long - NO int, short, char, double, etc!
    
         template<typename T>
         X(T) = delete;
    };
    
    X a(1);  //error - 1 is int 
    X b(1L); //ok    - 1L is long
    

    That means, the overload resolution is performed before the compiler sees the =delete part — and thus results in an error because the selected overload is found deleted.

    Hope that helps.

    0 讨论(0)
提交回复
热议问题