Non-Movable C++17 Unique Pointer











up vote
18
down vote

favorite












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




























    up vote
    18
    down vote

    favorite












    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


























      up vote
      18
      down vote

      favorite









      up vote
      18
      down vote

      favorite











      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 at 6:14

























      asked Nov 24 at 6:08









      tangy

      857720




      857720
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          17
          down vote



          accepted










          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 at 13:08


















          up vote
          3
          down vote













          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 at 6:22












          • @ShadowRanger You mean const std::unique_ptr<int>& ?
            – songyuanyao
            Nov 24 at 6:23










          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38
            – tangy
            Nov 24 at 6:31


















          up vote
          3
          down vote













          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 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








          up vote
          17
          down vote



          accepted










          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 at 13:08















          up vote
          17
          down vote



          accepted










          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 at 13:08













          up vote
          17
          down vote



          accepted







          up vote
          17
          down vote



          accepted






          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 at 6:24

























          answered Nov 24 at 6:18









          Yakk - Adam Nevraumont

          181k19188368




          181k19188368








          • 1




            If I read overload #6 correctly, the deleter trick should work. Neat!
            – Quentin
            Nov 24 at 13:08














          • 1




            If I read overload #6 correctly, the deleter trick should work. Neat!
            – Quentin
            Nov 24 at 13:08








          1




          1




          If I read overload #6 correctly, the deleter trick should work. Neat!
          – Quentin
          Nov 24 at 13:08




          If I read overload #6 correctly, the deleter trick should work. Neat!
          – Quentin
          Nov 24 at 13:08












          up vote
          3
          down vote













          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 at 6:22












          • @ShadowRanger You mean const std::unique_ptr<int>& ?
            – songyuanyao
            Nov 24 at 6:23










          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38
            – tangy
            Nov 24 at 6:31















          up vote
          3
          down vote













          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 at 6:22












          • @ShadowRanger You mean const std::unique_ptr<int>& ?
            – songyuanyao
            Nov 24 at 6:23










          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38
            – tangy
            Nov 24 at 6:31













          up vote
          3
          down vote










          up vote
          3
          down vote









          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 at 6:23

























          answered Nov 24 at 6:16









          songyuanyao

          89.4k11170233




          89.4k11170233












          • auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?
            – ShadowRanger
            Nov 24 at 6:22












          • @ShadowRanger You mean const std::unique_ptr<int>& ?
            – songyuanyao
            Nov 24 at 6:23










          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38
            – tangy
            Nov 24 at 6:31


















          • auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?
            – ShadowRanger
            Nov 24 at 6:22












          • @ShadowRanger You mean const std::unique_ptr<int>& ?
            – songyuanyao
            Nov 24 at 6:23










          • Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38
            – tangy
            Nov 24 at 6:31
















          auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?
          – ShadowRanger
          Nov 24 at 6:22






          auto& doesn't make it of non-reference type const std::unique_ptr<int>, does it?
          – ShadowRanger
          Nov 24 at 6:22














          @ShadowRanger You mean const std::unique_ptr<int>& ?
          – songyuanyao
          Nov 24 at 6:23




          @ShadowRanger You mean const std::unique_ptr<int>& ?
          – songyuanyao
          Nov 24 at 6:23












          Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38
          – tangy
          Nov 24 at 6:31




          Works across versions this way coliru.stacked-crooked.com/a/aef0f48df5604e38
          – tangy
          Nov 24 at 6:31










          up vote
          3
          down vote













          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 at 6:26















          up vote
          3
          down vote













          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 at 6:26













          up vote
          3
          down vote










          up vote
          3
          down vote









          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 at 9:44









          Jon Harper

          2,8802928




          2,8802928










          answered Nov 24 at 6:23









          Amos

          1,29221027




          1,29221027












          • 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 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 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 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 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.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • 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

          Bundesstraße 106

          Verónica Boquete

          Ida-Boy-Ed-Garten