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.
c++ c++11 c++17 unique-ptr
add a comment |
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.
c++ c++11 c++17 unique-ptr
add a comment |
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.
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 at 6:14
asked Nov 24 at 6:08
tangy
857720
857720
add a comment |
add a comment |
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
Nov 24 at 13:08
add a comment |
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
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 at 6:22
@ShadowRanger You meanconst 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
add a comment |
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
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
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
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
Nov 24 at 13:08
add a comment |
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
Nov 24 at 13:08
add a comment |
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.
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 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
add a comment |
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
add a comment |
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
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 at 6:22
@ShadowRanger You meanconst 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
add a comment |
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
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 at 6:22
@ShadowRanger You meanconst 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
add a comment |
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
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 at 6:23
answered Nov 24 at 6:16
songyuanyao
89.4k11170233
89.4k11170233
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 at 6:22
@ShadowRanger You meanconst 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
add a comment |
auto&
doesn't make it of non-reference typeconst std::unique_ptr<int>
, does it?
– ShadowRanger
Nov 24 at 6:22
@ShadowRanger You meanconst 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
add a comment |
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
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
add a comment |
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
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
add a comment |
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
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 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
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 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
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.
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.
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