Deleted implicitly-declared copy assignment operator











up vote
3
down vote

favorite












According to the C++ reference on Copy assignment operator:




A defaulted copy assignment operator for class T is defined as deleted if any of the following is true



T has a non-static data member of non-class type (or array thereof) that is const ...




I was hoping to create a case where I had a const class-type data member and a defaulted copy assignment operator not defined as deleted. In doing so, I found a discrepancy between clang and gcc. Consider the following code:



struct B {
void operator=(const B&) const {}
};

struct A {
const B b{};
A& operator=(const A&) = default;
};

int main() {
A a1{}, a2{};
a1 = a2; //only works with clang
B b1{}, b2{};
b1 = b2; //works in both
}


When I compile this with g++ -std=c++14 I get the following errors:



In member function ‘A& A::operator=(const A&)’:
error: non-static const member ‘const B A::b’, can’t use default assignment operator
note: synthesized method ‘A& A::operator=(const A&)’ first required here


This does, comma, however, compile with clang, as the reference seems to indicate that it should. Am I in error? Which compiler is correct?



I'm using gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) and clang version 6.0.0-1ubuntu2.










share|improve this question
























  • In general you want to use C++ since that gives the question a much wider audience than C++ version specific tags.
    – Shafik Yaghmour
    Nov 8 at 19:41















up vote
3
down vote

favorite












According to the C++ reference on Copy assignment operator:




A defaulted copy assignment operator for class T is defined as deleted if any of the following is true



T has a non-static data member of non-class type (or array thereof) that is const ...




I was hoping to create a case where I had a const class-type data member and a defaulted copy assignment operator not defined as deleted. In doing so, I found a discrepancy between clang and gcc. Consider the following code:



struct B {
void operator=(const B&) const {}
};

struct A {
const B b{};
A& operator=(const A&) = default;
};

int main() {
A a1{}, a2{};
a1 = a2; //only works with clang
B b1{}, b2{};
b1 = b2; //works in both
}


When I compile this with g++ -std=c++14 I get the following errors:



In member function ‘A& A::operator=(const A&)’:
error: non-static const member ‘const B A::b’, can’t use default assignment operator
note: synthesized method ‘A& A::operator=(const A&)’ first required here


This does, comma, however, compile with clang, as the reference seems to indicate that it should. Am I in error? Which compiler is correct?



I'm using gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) and clang version 6.0.0-1ubuntu2.










share|improve this question
























  • In general you want to use C++ since that gives the question a much wider audience than C++ version specific tags.
    – Shafik Yaghmour
    Nov 8 at 19:41













up vote
3
down vote

favorite









up vote
3
down vote

favorite











According to the C++ reference on Copy assignment operator:




A defaulted copy assignment operator for class T is defined as deleted if any of the following is true



T has a non-static data member of non-class type (or array thereof) that is const ...




I was hoping to create a case where I had a const class-type data member and a defaulted copy assignment operator not defined as deleted. In doing so, I found a discrepancy between clang and gcc. Consider the following code:



struct B {
void operator=(const B&) const {}
};

struct A {
const B b{};
A& operator=(const A&) = default;
};

int main() {
A a1{}, a2{};
a1 = a2; //only works with clang
B b1{}, b2{};
b1 = b2; //works in both
}


When I compile this with g++ -std=c++14 I get the following errors:



In member function ‘A& A::operator=(const A&)’:
error: non-static const member ‘const B A::b’, can’t use default assignment operator
note: synthesized method ‘A& A::operator=(const A&)’ first required here


This does, comma, however, compile with clang, as the reference seems to indicate that it should. Am I in error? Which compiler is correct?



I'm using gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) and clang version 6.0.0-1ubuntu2.










share|improve this question















According to the C++ reference on Copy assignment operator:




A defaulted copy assignment operator for class T is defined as deleted if any of the following is true



T has a non-static data member of non-class type (or array thereof) that is const ...




I was hoping to create a case where I had a const class-type data member and a defaulted copy assignment operator not defined as deleted. In doing so, I found a discrepancy between clang and gcc. Consider the following code:



struct B {
void operator=(const B&) const {}
};

struct A {
const B b{};
A& operator=(const A&) = default;
};

int main() {
A a1{}, a2{};
a1 = a2; //only works with clang
B b1{}, b2{};
b1 = b2; //works in both
}


When I compile this with g++ -std=c++14 I get the following errors:



In member function ‘A& A::operator=(const A&)’:
error: non-static const member ‘const B A::b’, can’t use default assignment operator
note: synthesized method ‘A& A::operator=(const A&)’ first required here


This does, comma, however, compile with clang, as the reference seems to indicate that it should. Am I in error? Which compiler is correct?



I'm using gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) and clang version 6.0.0-1ubuntu2.







c++ g++ c++14 clang++ assignment-operator






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 19:40









Shafik Yaghmour

123k23309510




123k23309510










asked Nov 8 at 18:06









Nathan Chappell

1007




1007












  • In general you want to use C++ since that gives the question a much wider audience than C++ version specific tags.
    – Shafik Yaghmour
    Nov 8 at 19:41


















  • In general you want to use C++ since that gives the question a much wider audience than C++ version specific tags.
    – Shafik Yaghmour
    Nov 8 at 19:41
















In general you want to use C++ since that gives the question a much wider audience than C++ version specific tags.
– Shafik Yaghmour
Nov 8 at 19:41




In general you want to use C++ since that gives the question a much wider audience than C++ version specific tags.
– Shafik Yaghmour
Nov 8 at 19:41












2 Answers
2






active

oldest

votes

















up vote
1
down vote



accepted










It seems that clang is right,



Although not yet confirmed, there is a report on the subject for gcc
and as it was pointed out, the two rules relevant to this case don't apply



[class.copy.assign]/7




(7.2) a non-static data member of const non-class type (or array thereof), or



[...]



(7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.







share|improve this answer




























    up vote
    1
    down vote













    It sure looks like clang is correct, section [class.copy.assign]p7 says:




    A defaulted copy/move assignment operator for class X is defined as
    deleted if X has:




    • (7.1) a variant member with a non-trivial corresponding assignment operator and X is a union-like class, or

    • (7.2) a non-static data member of const non-class type (or array thereof), or

    • (7.3) a non-static data member of reference type, or

    • (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because
      overload resolution ([over.match]), as applied to find M's
      corresponding assignment operator, results in an ambiguity or a
      function that is deleted or inaccessible from the defaulted assignment
      operator.


    A defaulted move assignment operator that is defined as deleted is
    ignored by overload resolution ([over.match], [over.over]).




    and none of those cases hold.



    Although I have to say a const copy assignment operator that returns void feels novel, the wording in [class.copy.assign]p1 sure seems to allow.



    There is an open gcc bug report for a similar case Const subobject with const assignment operator, but operator anyway deleted with code as follows:



    class bar
    {
    public:
    bar() {}

    bar const & operator=(bar const &) const
    {
    return *this;
    }
    };

    class foo
    {
    bar const v;
    };

    int main()
    {
    foo a;

    a = foo();
    }


    The reporter points out the same section as I do.






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














       

      draft saved


      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53213681%2fdeleted-implicitly-declared-copy-assignment-operator%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      1
      down vote



      accepted










      It seems that clang is right,



      Although not yet confirmed, there is a report on the subject for gcc
      and as it was pointed out, the two rules relevant to this case don't apply



      [class.copy.assign]/7




      (7.2) a non-static data member of const non-class type (or array thereof), or



      [...]



      (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.







      share|improve this answer

























        up vote
        1
        down vote



        accepted










        It seems that clang is right,



        Although not yet confirmed, there is a report on the subject for gcc
        and as it was pointed out, the two rules relevant to this case don't apply



        [class.copy.assign]/7




        (7.2) a non-static data member of const non-class type (or array thereof), or



        [...]



        (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.







        share|improve this answer























          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          It seems that clang is right,



          Although not yet confirmed, there is a report on the subject for gcc
          and as it was pointed out, the two rules relevant to this case don't apply



          [class.copy.assign]/7




          (7.2) a non-static data member of const non-class type (or array thereof), or



          [...]



          (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.







          share|improve this answer












          It seems that clang is right,



          Although not yet confirmed, there is a report on the subject for gcc
          and as it was pointed out, the two rules relevant to this case don't apply



          [class.copy.assign]/7




          (7.2) a non-static data member of const non-class type (or array thereof), or



          [...]



          (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.








          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 8 at 18:55









          Jans

          5,81612131




          5,81612131
























              up vote
              1
              down vote













              It sure looks like clang is correct, section [class.copy.assign]p7 says:




              A defaulted copy/move assignment operator for class X is defined as
              deleted if X has:




              • (7.1) a variant member with a non-trivial corresponding assignment operator and X is a union-like class, or

              • (7.2) a non-static data member of const non-class type (or array thereof), or

              • (7.3) a non-static data member of reference type, or

              • (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because
                overload resolution ([over.match]), as applied to find M's
                corresponding assignment operator, results in an ambiguity or a
                function that is deleted or inaccessible from the defaulted assignment
                operator.


              A defaulted move assignment operator that is defined as deleted is
              ignored by overload resolution ([over.match], [over.over]).




              and none of those cases hold.



              Although I have to say a const copy assignment operator that returns void feels novel, the wording in [class.copy.assign]p1 sure seems to allow.



              There is an open gcc bug report for a similar case Const subobject with const assignment operator, but operator anyway deleted with code as follows:



              class bar
              {
              public:
              bar() {}

              bar const & operator=(bar const &) const
              {
              return *this;
              }
              };

              class foo
              {
              bar const v;
              };

              int main()
              {
              foo a;

              a = foo();
              }


              The reporter points out the same section as I do.






              share|improve this answer



























                up vote
                1
                down vote













                It sure looks like clang is correct, section [class.copy.assign]p7 says:




                A defaulted copy/move assignment operator for class X is defined as
                deleted if X has:




                • (7.1) a variant member with a non-trivial corresponding assignment operator and X is a union-like class, or

                • (7.2) a non-static data member of const non-class type (or array thereof), or

                • (7.3) a non-static data member of reference type, or

                • (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because
                  overload resolution ([over.match]), as applied to find M's
                  corresponding assignment operator, results in an ambiguity or a
                  function that is deleted or inaccessible from the defaulted assignment
                  operator.


                A defaulted move assignment operator that is defined as deleted is
                ignored by overload resolution ([over.match], [over.over]).




                and none of those cases hold.



                Although I have to say a const copy assignment operator that returns void feels novel, the wording in [class.copy.assign]p1 sure seems to allow.



                There is an open gcc bug report for a similar case Const subobject with const assignment operator, but operator anyway deleted with code as follows:



                class bar
                {
                public:
                bar() {}

                bar const & operator=(bar const &) const
                {
                return *this;
                }
                };

                class foo
                {
                bar const v;
                };

                int main()
                {
                foo a;

                a = foo();
                }


                The reporter points out the same section as I do.






                share|improve this answer

























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  It sure looks like clang is correct, section [class.copy.assign]p7 says:




                  A defaulted copy/move assignment operator for class X is defined as
                  deleted if X has:




                  • (7.1) a variant member with a non-trivial corresponding assignment operator and X is a union-like class, or

                  • (7.2) a non-static data member of const non-class type (or array thereof), or

                  • (7.3) a non-static data member of reference type, or

                  • (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because
                    overload resolution ([over.match]), as applied to find M's
                    corresponding assignment operator, results in an ambiguity or a
                    function that is deleted or inaccessible from the defaulted assignment
                    operator.


                  A defaulted move assignment operator that is defined as deleted is
                  ignored by overload resolution ([over.match], [over.over]).




                  and none of those cases hold.



                  Although I have to say a const copy assignment operator that returns void feels novel, the wording in [class.copy.assign]p1 sure seems to allow.



                  There is an open gcc bug report for a similar case Const subobject with const assignment operator, but operator anyway deleted with code as follows:



                  class bar
                  {
                  public:
                  bar() {}

                  bar const & operator=(bar const &) const
                  {
                  return *this;
                  }
                  };

                  class foo
                  {
                  bar const v;
                  };

                  int main()
                  {
                  foo a;

                  a = foo();
                  }


                  The reporter points out the same section as I do.






                  share|improve this answer














                  It sure looks like clang is correct, section [class.copy.assign]p7 says:




                  A defaulted copy/move assignment operator for class X is defined as
                  deleted if X has:




                  • (7.1) a variant member with a non-trivial corresponding assignment operator and X is a union-like class, or

                  • (7.2) a non-static data member of const non-class type (or array thereof), or

                  • (7.3) a non-static data member of reference type, or

                  • (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because
                    overload resolution ([over.match]), as applied to find M's
                    corresponding assignment operator, results in an ambiguity or a
                    function that is deleted or inaccessible from the defaulted assignment
                    operator.


                  A defaulted move assignment operator that is defined as deleted is
                  ignored by overload resolution ([over.match], [over.over]).




                  and none of those cases hold.



                  Although I have to say a const copy assignment operator that returns void feels novel, the wording in [class.copy.assign]p1 sure seems to allow.



                  There is an open gcc bug report for a similar case Const subobject with const assignment operator, but operator anyway deleted with code as follows:



                  class bar
                  {
                  public:
                  bar() {}

                  bar const & operator=(bar const &) const
                  {
                  return *this;
                  }
                  };

                  class foo
                  {
                  bar const v;
                  };

                  int main()
                  {
                  foo a;

                  a = foo();
                  }


                  The reporter points out the same section as I do.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 10 at 23:18

























                  answered Nov 8 at 18:36









                  Shafik Yaghmour

                  123k23309510




                  123k23309510






























                       

                      draft saved


                      draft discarded



















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53213681%2fdeleted-implicitly-declared-copy-assignment-operator%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Bressuire

                      Vorschmack

                      Quarantine