Non-Movable C++17 Unique Pointer











up vote
9
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
    9
    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
      9
      down vote

      favorite









      up vote
      9
      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

      663518




      663518
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          14
          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
            2 days ago


















          up vote
          2
          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
          2
          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',
          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
          14
          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
            2 days ago















          up vote
          14
          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
            2 days ago













          up vote
          14
          down vote



          accepted







          up vote
          14
          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

          179k19186365




          179k19186365








          • 1




            If I read overload #6 correctly, the deleter trick should work. Neat!
            – Quentin
            2 days ago














          • 1




            If I read overload #6 correctly, the deleter trick should work. Neat!
            – Quentin
            2 days ago








          1




          1




          If I read overload #6 correctly, the deleter trick should work. Neat!
          – Quentin
          2 days ago




          If I read overload #6 correctly, the deleter trick should work. Neat!
          – Quentin
          2 days ago












          up vote
          2
          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
          2
          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
          2
          down vote










          up vote
          2
          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

          88.6k11170232




          88.6k11170232












          • 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
          2
          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
          2
          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
          2
          down vote










          up vote
          2
          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 yesterday









          Jon Harper

          2,8492928




          2,8492928










          answered Nov 24 at 6:23









          Amos

          1,127927




          1,127927












          • 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



















































           


          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

          Morgemoulin

          Scott Moir

          Souastre