Can copy constructors of containers be defined as deleted for non-copyable value types?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
9
down vote

favorite
1












If we have a container with non-copyable value type, such a container class still defines the copy constructor, just it may not be invoked.



using T = std::vector<std::unique_ptr<int>>;
std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)


This may cause "hidden" problems such as the one discussed here: Does Visual Studio 2017 need an explicit move constructor declaration?.



My question is if Standard library implementations may define such copy constructor as conditionally deleted, namely deleted in case of non-copyable value types. It would make perfect sense to me (at least until there are C++ concepts). Would such implementation be Standard-compliant?










share|improve this question



























    up vote
    9
    down vote

    favorite
    1












    If we have a container with non-copyable value type, such a container class still defines the copy constructor, just it may not be invoked.



    using T = std::vector<std::unique_ptr<int>>;
    std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)


    This may cause "hidden" problems such as the one discussed here: Does Visual Studio 2017 need an explicit move constructor declaration?.



    My question is if Standard library implementations may define such copy constructor as conditionally deleted, namely deleted in case of non-copyable value types. It would make perfect sense to me (at least until there are C++ concepts). Would such implementation be Standard-compliant?










    share|improve this question

























      up vote
      9
      down vote

      favorite
      1









      up vote
      9
      down vote

      favorite
      1






      1





      If we have a container with non-copyable value type, such a container class still defines the copy constructor, just it may not be invoked.



      using T = std::vector<std::unique_ptr<int>>;
      std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)


      This may cause "hidden" problems such as the one discussed here: Does Visual Studio 2017 need an explicit move constructor declaration?.



      My question is if Standard library implementations may define such copy constructor as conditionally deleted, namely deleted in case of non-copyable value types. It would make perfect sense to me (at least until there are C++ concepts). Would such implementation be Standard-compliant?










      share|improve this question















      If we have a container with non-copyable value type, such a container class still defines the copy constructor, just it may not be invoked.



      using T = std::vector<std::unique_ptr<int>>;
      std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)


      This may cause "hidden" problems such as the one discussed here: Does Visual Studio 2017 need an explicit move constructor declaration?.



      My question is if Standard library implementations may define such copy constructor as conditionally deleted, namely deleted in case of non-copyable value types. It would make perfect sense to me (at least until there are C++ concepts). Would such implementation be Standard-compliant?







      c++ containers language-lawyer copy-constructor noncopyable






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 4 hours ago

























      asked 4 hours ago









      Daniel Langr

      6,1192243




      6,1192243






















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          4
          down vote













          This is not possible ever since vector got incomplete type support:



          struct E 
          std::vector<E> e;
          ;


          E is copyable iff std::vector<E> is copyable, and std::vector<E> is copyable iff E is copyable. Turtles all the way down.



          Even before that, because the allocator's construct can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.






          share|improve this answer



























            up vote
            3
            down vote













            For a short answer: no.
            If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:



            vector(const vector& other);



            Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).




            The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>'s copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>> does not satisfy CopyConstructible requirement, which is very much like having a deleted copy constructor.



            As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.






            share|improve this answer



























              up vote
              2
              down vote













              As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:




              For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
              [ Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
              — end note
               ]







              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%2f53210201%2fcan-copy-constructors-of-containers-be-defined-as-deleted-for-non-copyable-value%23new-answer', 'question_page');

                );

                Post as a guest






























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes








                up vote
                4
                down vote













                This is not possible ever since vector got incomplete type support:



                struct E 
                std::vector<E> e;
                ;


                E is copyable iff std::vector<E> is copyable, and std::vector<E> is copyable iff E is copyable. Turtles all the way down.



                Even before that, because the allocator's construct can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.






                share|improve this answer
























                  up vote
                  4
                  down vote













                  This is not possible ever since vector got incomplete type support:



                  struct E 
                  std::vector<E> e;
                  ;


                  E is copyable iff std::vector<E> is copyable, and std::vector<E> is copyable iff E is copyable. Turtles all the way down.



                  Even before that, because the allocator's construct can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.






                  share|improve this answer






















                    up vote
                    4
                    down vote










                    up vote
                    4
                    down vote









                    This is not possible ever since vector got incomplete type support:



                    struct E 
                    std::vector<E> e;
                    ;


                    E is copyable iff std::vector<E> is copyable, and std::vector<E> is copyable iff E is copyable. Turtles all the way down.



                    Even before that, because the allocator's construct can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.






                    share|improve this answer












                    This is not possible ever since vector got incomplete type support:



                    struct E 
                    std::vector<E> e;
                    ;


                    E is copyable iff std::vector<E> is copyable, and std::vector<E> is copyable iff E is copyable. Turtles all the way down.



                    Even before that, because the allocator's construct can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 37 mins ago









                    T.C.

                    103k13208312




                    103k13208312






















                        up vote
                        3
                        down vote













                        For a short answer: no.
                        If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:



                        vector(const vector& other);



                        Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).




                        The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>'s copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>> does not satisfy CopyConstructible requirement, which is very much like having a deleted copy constructor.



                        As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.






                        share|improve this answer
























                          up vote
                          3
                          down vote













                          For a short answer: no.
                          If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:



                          vector(const vector& other);



                          Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).




                          The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>'s copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>> does not satisfy CopyConstructible requirement, which is very much like having a deleted copy constructor.



                          As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.






                          share|improve this answer






















                            up vote
                            3
                            down vote










                            up vote
                            3
                            down vote









                            For a short answer: no.
                            If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:



                            vector(const vector& other);



                            Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).




                            The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>'s copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>> does not satisfy CopyConstructible requirement, which is very much like having a deleted copy constructor.



                            As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.






                            share|improve this answer












                            For a short answer: no.
                            If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:



                            vector(const vector& other);



                            Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).




                            The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>'s copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>> does not satisfy CopyConstructible requirement, which is very much like having a deleted copy constructor.



                            As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered 53 mins ago









                            Julien Villemure-Fréchette

                            515




                            515




















                                up vote
                                2
                                down vote













                                As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:




                                For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
                                [ Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
                                — end note
                                 ]







                                share|improve this answer
























                                  up vote
                                  2
                                  down vote













                                  As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:




                                  For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
                                  [ Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
                                  — end note
                                   ]







                                  share|improve this answer






















                                    up vote
                                    2
                                    down vote










                                    up vote
                                    2
                                    down vote









                                    As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:




                                    For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
                                    [ Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
                                    — end note
                                     ]







                                    share|improve this answer












                                    As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:




                                    For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
                                    [ Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
                                    — end note
                                     ]








                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered 25 mins ago









                                    Shafik Yaghmour

                                    121k23304503




                                    121k23304503



























                                         

                                        draft saved


                                        draft discarded















































                                         


                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function ()
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53210201%2fcan-copy-constructors-of-containers-be-defined-as-deleted-for-non-copyable-value%23new-answer', 'question_page');

                                        );

                                        Post as a guest













































































                                        Comments

                                        Popular posts from this blog

                                        What does second last employer means? [closed]

                                        Installing NextGIS Connect into QGIS 3?

                                        One-line joke