Non-Movable C++17 Unique Pointer












18















I came across this answer Prevent moving of a unique_ptr C++11. However while trying it out on a compiler online, this works with C++11(std::move compiler error) but with C++17, I'm seeing that the std::move below is successful. Shouldn't the compiler throw an error on that line? Also if some semantics have changed in C++17, what is the correct way to create a non movable unique_ptr in C++17 and onward.



template <typename T>
using scoped_ptr = const std::unique_ptr<T>;

int main()
{
auto p = scoped_ptr<int>(new int(5));
auto p2 = std::move(p); // should be error?
std::cout << *p2 << std::endl; // 5
return 0;
}


You can try it online here.










share|improve this question





























    18















    I came across this answer Prevent moving of a unique_ptr C++11. However while trying it out on a compiler online, this works with C++11(std::move compiler error) but with C++17, I'm seeing that the std::move below is successful. Shouldn't the compiler throw an error on that line? Also if some semantics have changed in C++17, what is the correct way to create a non movable unique_ptr in C++17 and onward.



    template <typename T>
    using scoped_ptr = const std::unique_ptr<T>;

    int main()
    {
    auto p = scoped_ptr<int>(new int(5));
    auto p2 = std::move(p); // should be error?
    std::cout << *p2 << std::endl; // 5
    return 0;
    }


    You can try it online here.










    share|improve this question



























      18












      18








      18








      I came across this answer Prevent moving of a unique_ptr C++11. However while trying it out on a compiler online, this works with C++11(std::move compiler error) but with C++17, I'm seeing that the std::move below is successful. Shouldn't the compiler throw an error on that line? Also if some semantics have changed in C++17, what is the correct way to create a non movable unique_ptr in C++17 and onward.



      template <typename T>
      using scoped_ptr = const std::unique_ptr<T>;

      int main()
      {
      auto p = scoped_ptr<int>(new int(5));
      auto p2 = std::move(p); // should be error?
      std::cout << *p2 << std::endl; // 5
      return 0;
      }


      You can try it online here.










      share|improve this question
















      I came across this answer Prevent moving of a unique_ptr C++11. However while trying it out on a compiler online, this works with C++11(std::move compiler error) but with C++17, I'm seeing that the std::move below is successful. Shouldn't the compiler throw an error on that line? Also if some semantics have changed in C++17, what is the correct way to create a non movable unique_ptr in C++17 and onward.



      template <typename T>
      using scoped_ptr = const std::unique_ptr<T>;

      int main()
      {
      auto p = scoped_ptr<int>(new int(5));
      auto p2 = std::move(p); // should be error?
      std::cout << *p2 << std::endl; // 5
      return 0;
      }


      You can try it online here.







      c++ c++11 c++17 unique-ptr






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 24 '18 at 6:14







      tangy

















      asked Nov 24 '18 at 6:08









      tangytangy

      1,010720




      1,010720
























          3 Answers
          3






          active

          oldest

          votes


















          17














          p is not const. See here for it to fail the way you expect.



          auto deduces like a template<class T>void foo(T) does. T is never deduced as const, and neither is auto p=.



          Meanwhile, the auto p = line works because you compiled it in c++17 mode. In c++11 it does not compile. This is because how prvalues differ in 17; some call the difference guaranteed elision.



          If you want an immobile unique ptr:



          template<class T, class D>
          struct immobile_ptr:private std::unique_ptr<T, D>{
          using unique_ptr<T>::operator*;
          using unique_ptr<T>::operator->;
          using unique_ptr<T>::get;
          using unique_ptr<T>::operator bool;
          // etc

          // manually forward some ctors, as using grabs some move ctors in this case
          };
          template<class T, class...Args>
          immobile_ptr<T> make_immobile_ptr(Args&&...args); // todo


          an alternative might be to take a unique ptr with an immobile destroyer.



          template<class X>
          struct nomove_destroy:std::destroy<T>{
          nomove_destroy(nomove_destroy&&)=delete;
          nomove_destroy()=default;
          nomove_destroy& operator=(nomove_destroy&&)=delete;
          };
          template<class T>
          using nomove_ptr=std::unique_ptr<T,nomove_destroy<T>>;


          But I am uncertain if that will work.






          share|improve this answer





















          • 1





            If I read overload #6 correctly, the deleter trick should work. Neat!

            – Quentin
            Nov 24 '18 at 13:08



















          3














          Note that p is declared as non-reference type, the const part of the argument scoped_ptr<int>(new int(5)) is ignored in type deduction. Then the type deduction result for p is std::unique_ptr<int>, not const std::unique_ptr<int> (i.e. scoped_ptr<int> as you expected).



          What you want might be



          auto& p = scoped_ptr<int>(new int(5)); // p is of type const std::unique_ptr<int>& now





          share|improve this answer


























          • auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?

            – ShadowRanger
            Nov 24 '18 at 6:22













          • @ShadowRanger You mean const std::unique_ptr<int>& ?

            – songyuanyao
            Nov 24 '18 at 6:23











          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38

            – tangy
            Nov 24 '18 at 6:31



















          3














          Welcome to the world of type deduction in C++. Try



          auto & p = scoped_ptr<int>(new int(5));


          or



          auto && p = scoped_ptr<int>(new int(5));


          instead. This lecture may be helpful: https://www.youtube.com/watch?v=wQxj20X-tIU






          share|improve this answer


























          • Thanks for the suggested lecture - I think I need to watch this and read the relevant material from Modern Effective C++ again :)

            – tangy
            Nov 24 '18 at 6:26











          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',
          autoActivateHeartbeat: false,
          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%2f53455630%2fnon-movable-c17-unique-pointer%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          17














          p is not const. See here for it to fail the way you expect.



          auto deduces like a template<class T>void foo(T) does. T is never deduced as const, and neither is auto p=.



          Meanwhile, the auto p = line works because you compiled it in c++17 mode. In c++11 it does not compile. This is because how prvalues differ in 17; some call the difference guaranteed elision.



          If you want an immobile unique ptr:



          template<class T, class D>
          struct immobile_ptr:private std::unique_ptr<T, D>{
          using unique_ptr<T>::operator*;
          using unique_ptr<T>::operator->;
          using unique_ptr<T>::get;
          using unique_ptr<T>::operator bool;
          // etc

          // manually forward some ctors, as using grabs some move ctors in this case
          };
          template<class T, class...Args>
          immobile_ptr<T> make_immobile_ptr(Args&&...args); // todo


          an alternative might be to take a unique ptr with an immobile destroyer.



          template<class X>
          struct nomove_destroy:std::destroy<T>{
          nomove_destroy(nomove_destroy&&)=delete;
          nomove_destroy()=default;
          nomove_destroy& operator=(nomove_destroy&&)=delete;
          };
          template<class T>
          using nomove_ptr=std::unique_ptr<T,nomove_destroy<T>>;


          But I am uncertain if that will work.






          share|improve this answer





















          • 1





            If I read overload #6 correctly, the deleter trick should work. Neat!

            – Quentin
            Nov 24 '18 at 13:08
















          17














          p is not const. See here for it to fail the way you expect.



          auto deduces like a template<class T>void foo(T) does. T is never deduced as const, and neither is auto p=.



          Meanwhile, the auto p = line works because you compiled it in c++17 mode. In c++11 it does not compile. This is because how prvalues differ in 17; some call the difference guaranteed elision.



          If you want an immobile unique ptr:



          template<class T, class D>
          struct immobile_ptr:private std::unique_ptr<T, D>{
          using unique_ptr<T>::operator*;
          using unique_ptr<T>::operator->;
          using unique_ptr<T>::get;
          using unique_ptr<T>::operator bool;
          // etc

          // manually forward some ctors, as using grabs some move ctors in this case
          };
          template<class T, class...Args>
          immobile_ptr<T> make_immobile_ptr(Args&&...args); // todo


          an alternative might be to take a unique ptr with an immobile destroyer.



          template<class X>
          struct nomove_destroy:std::destroy<T>{
          nomove_destroy(nomove_destroy&&)=delete;
          nomove_destroy()=default;
          nomove_destroy& operator=(nomove_destroy&&)=delete;
          };
          template<class T>
          using nomove_ptr=std::unique_ptr<T,nomove_destroy<T>>;


          But I am uncertain if that will work.






          share|improve this answer





















          • 1





            If I read overload #6 correctly, the deleter trick should work. Neat!

            – Quentin
            Nov 24 '18 at 13:08














          17












          17








          17







          p is not const. See here for it to fail the way you expect.



          auto deduces like a template<class T>void foo(T) does. T is never deduced as const, and neither is auto p=.



          Meanwhile, the auto p = line works because you compiled it in c++17 mode. In c++11 it does not compile. This is because how prvalues differ in 17; some call the difference guaranteed elision.



          If you want an immobile unique ptr:



          template<class T, class D>
          struct immobile_ptr:private std::unique_ptr<T, D>{
          using unique_ptr<T>::operator*;
          using unique_ptr<T>::operator->;
          using unique_ptr<T>::get;
          using unique_ptr<T>::operator bool;
          // etc

          // manually forward some ctors, as using grabs some move ctors in this case
          };
          template<class T, class...Args>
          immobile_ptr<T> make_immobile_ptr(Args&&...args); // todo


          an alternative might be to take a unique ptr with an immobile destroyer.



          template<class X>
          struct nomove_destroy:std::destroy<T>{
          nomove_destroy(nomove_destroy&&)=delete;
          nomove_destroy()=default;
          nomove_destroy& operator=(nomove_destroy&&)=delete;
          };
          template<class T>
          using nomove_ptr=std::unique_ptr<T,nomove_destroy<T>>;


          But I am uncertain if that will work.






          share|improve this answer















          p is not const. See here for it to fail the way you expect.



          auto deduces like a template<class T>void foo(T) does. T is never deduced as const, and neither is auto p=.



          Meanwhile, the auto p = line works because you compiled it in c++17 mode. In c++11 it does not compile. This is because how prvalues differ in 17; some call the difference guaranteed elision.



          If you want an immobile unique ptr:



          template<class T, class D>
          struct immobile_ptr:private std::unique_ptr<T, D>{
          using unique_ptr<T>::operator*;
          using unique_ptr<T>::operator->;
          using unique_ptr<T>::get;
          using unique_ptr<T>::operator bool;
          // etc

          // manually forward some ctors, as using grabs some move ctors in this case
          };
          template<class T, class...Args>
          immobile_ptr<T> make_immobile_ptr(Args&&...args); // todo


          an alternative might be to take a unique ptr with an immobile destroyer.



          template<class X>
          struct nomove_destroy:std::destroy<T>{
          nomove_destroy(nomove_destroy&&)=delete;
          nomove_destroy()=default;
          nomove_destroy& operator=(nomove_destroy&&)=delete;
          };
          template<class T>
          using nomove_ptr=std::unique_ptr<T,nomove_destroy<T>>;


          But I am uncertain if that will work.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 24 '18 at 6:24

























          answered Nov 24 '18 at 6:18









          Yakk - Adam NevraumontYakk - Adam Nevraumont

          186k19198379




          186k19198379








          • 1





            If I read overload #6 correctly, the deleter trick should work. Neat!

            – Quentin
            Nov 24 '18 at 13:08














          • 1





            If I read overload #6 correctly, the deleter trick should work. Neat!

            – Quentin
            Nov 24 '18 at 13:08








          1




          1





          If I read overload #6 correctly, the deleter trick should work. Neat!

          – Quentin
          Nov 24 '18 at 13:08





          If I read overload #6 correctly, the deleter trick should work. Neat!

          – Quentin
          Nov 24 '18 at 13:08













          3














          Note that p is declared as non-reference type, the const part of the argument scoped_ptr<int>(new int(5)) is ignored in type deduction. Then the type deduction result for p is std::unique_ptr<int>, not const std::unique_ptr<int> (i.e. scoped_ptr<int> as you expected).



          What you want might be



          auto& p = scoped_ptr<int>(new int(5)); // p is of type const std::unique_ptr<int>& now





          share|improve this answer


























          • auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?

            – ShadowRanger
            Nov 24 '18 at 6:22













          • @ShadowRanger You mean const std::unique_ptr<int>& ?

            – songyuanyao
            Nov 24 '18 at 6:23











          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38

            – tangy
            Nov 24 '18 at 6:31
















          3














          Note that p is declared as non-reference type, the const part of the argument scoped_ptr<int>(new int(5)) is ignored in type deduction. Then the type deduction result for p is std::unique_ptr<int>, not const std::unique_ptr<int> (i.e. scoped_ptr<int> as you expected).



          What you want might be



          auto& p = scoped_ptr<int>(new int(5)); // p is of type const std::unique_ptr<int>& now





          share|improve this answer


























          • auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?

            – ShadowRanger
            Nov 24 '18 at 6:22













          • @ShadowRanger You mean const std::unique_ptr<int>& ?

            – songyuanyao
            Nov 24 '18 at 6:23











          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38

            – tangy
            Nov 24 '18 at 6:31














          3












          3








          3







          Note that p is declared as non-reference type, the const part of the argument scoped_ptr<int>(new int(5)) is ignored in type deduction. Then the type deduction result for p is std::unique_ptr<int>, not const std::unique_ptr<int> (i.e. scoped_ptr<int> as you expected).



          What you want might be



          auto& p = scoped_ptr<int>(new int(5)); // p is of type const std::unique_ptr<int>& now





          share|improve this answer















          Note that p is declared as non-reference type, the const part of the argument scoped_ptr<int>(new int(5)) is ignored in type deduction. Then the type deduction result for p is std::unique_ptr<int>, not const std::unique_ptr<int> (i.e. scoped_ptr<int> as you expected).



          What you want might be



          auto& p = scoped_ptr<int>(new int(5)); // p is of type const std::unique_ptr<int>& now






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 24 '18 at 6:23

























          answered Nov 24 '18 at 6:16









          songyuanyaosongyuanyao

          92k11175240




          92k11175240













          • auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?

            – ShadowRanger
            Nov 24 '18 at 6:22













          • @ShadowRanger You mean const std::unique_ptr<int>& ?

            – songyuanyao
            Nov 24 '18 at 6:23











          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38

            – tangy
            Nov 24 '18 at 6:31



















          • auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?

            – ShadowRanger
            Nov 24 '18 at 6:22













          • @ShadowRanger You mean const std::unique_ptr<int>& ?

            – songyuanyao
            Nov 24 '18 at 6:23











          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38

            – tangy
            Nov 24 '18 at 6:31

















          auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?

          – ShadowRanger
          Nov 24 '18 at 6:22







          auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?

          – ShadowRanger
          Nov 24 '18 at 6:22















          @ShadowRanger You mean const std::unique_ptr<int>& ?

          – songyuanyao
          Nov 24 '18 at 6:23





          @ShadowRanger You mean const std::unique_ptr<int>& ?

          – songyuanyao
          Nov 24 '18 at 6:23













          Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38

          – tangy
          Nov 24 '18 at 6:31





          Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38

          – tangy
          Nov 24 '18 at 6:31











          3














          Welcome to the world of type deduction in C++. Try



          auto & p = scoped_ptr<int>(new int(5));


          or



          auto && p = scoped_ptr<int>(new int(5));


          instead. This lecture may be helpful: https://www.youtube.com/watch?v=wQxj20X-tIU






          share|improve this answer


























          • Thanks for the suggested lecture - I think I need to watch this and read the relevant material from Modern Effective C++ again :)

            – tangy
            Nov 24 '18 at 6:26
















          3














          Welcome to the world of type deduction in C++. Try



          auto & p = scoped_ptr<int>(new int(5));


          or



          auto && p = scoped_ptr<int>(new int(5));


          instead. This lecture may be helpful: https://www.youtube.com/watch?v=wQxj20X-tIU






          share|improve this answer


























          • Thanks for the suggested lecture - I think I need to watch this and read the relevant material from Modern Effective C++ again :)

            – tangy
            Nov 24 '18 at 6:26














          3












          3








          3







          Welcome to the world of type deduction in C++. Try



          auto & p = scoped_ptr<int>(new int(5));


          or



          auto && p = scoped_ptr<int>(new int(5));


          instead. This lecture may be helpful: https://www.youtube.com/watch?v=wQxj20X-tIU






          share|improve this answer















          Welcome to the world of type deduction in C++. Try



          auto & p = scoped_ptr<int>(new int(5));


          or



          auto && p = scoped_ptr<int>(new int(5));


          instead. This lecture may be helpful: https://www.youtube.com/watch?v=wQxj20X-tIU







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 25 '18 at 9:44









          Jon Harper

          2,9482929




          2,9482929










          answered Nov 24 '18 at 6:23









          AmosAmos

          1,67531029




          1,67531029













          • Thanks for the suggested lecture - I think I need to watch this and read the relevant material from Modern Effective C++ again :)

            – tangy
            Nov 24 '18 at 6:26



















          • Thanks for the suggested lecture - I think I need to watch this and read the relevant material from Modern Effective C++ again :)

            – tangy
            Nov 24 '18 at 6:26

















          Thanks for the suggested lecture - I think I need to watch this and read the relevant material from Modern Effective C++ again :)

          – tangy
          Nov 24 '18 at 6:26





          Thanks for the suggested lecture - I think I need to watch this and read the relevant material from Modern Effective C++ again :)

          – tangy
          Nov 24 '18 at 6:26


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53455630%2fnon-movable-c17-unique-pointer%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

          Wiesbaden

          Marschland

          Dieringhausen