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.
c++ c++11 c++17 unique-ptr
add a comment |
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.
c++ c++11 c++17 unique-ptr
add a comment |
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.
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
663518
663518
add a comment |
add a comment |
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
2 days ago
add a comment |
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
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
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
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 |
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
2 days ago
add a comment |
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.
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
2 days ago
add a comment |
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.
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
179k19186365
179k19186365
1
If I read overload #6 correctly, the deleter trick should work. Neat!
– Quentin
2 days ago
add a comment |
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
add a comment |
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
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
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
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
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
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
88.6k11170232
88.6k11170232
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
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
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
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
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
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
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 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
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 |
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