Non-Movable C++17 Unique Pointer
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
add a comment |
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
add a comment |
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
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
c++ c++11 c++17 unique-ptr
edited Nov 24 '18 at 6:14
tangy
asked Nov 24 '18 at 6:08
tangytangy
1,010720
1,010720
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
Nov 24 '18 at 13:08
add a comment |
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
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 '18 at 6:22
@ShadowRanger You meanconst 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
add a comment |
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
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
Nov 24 '18 at 13:08
add a comment |
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
Nov 24 '18 at 13:08
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 '18 at 6:22
@ShadowRanger You meanconst 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
add a comment |
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
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 '18 at 6:22
@ShadowRanger You meanconst 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
add a comment |
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
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
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 typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 '18 at 6:22
@ShadowRanger You meanconst 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
add a comment |
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 '18 at 6:22
@ShadowRanger You meanconst 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
add a comment |
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
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
add a comment |
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
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
add a comment |
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
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
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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