Log in

View Full Version : Should we use std::unique_ptr?


egaudet
15-11-2016, 10:43
When creating a new project and using "Robot C++ Project" (command-based), the example subsystem is declared as a std::unique_ptr rather than an old-style standard pointer:

static std::unique_ptr<ExampleSubsystem> examplesubsystem;
vs
ExampleSubsystem *examplesubsystem;

Given that the example code is using this pointer type, I figured it was probably a good idea for us to start using it too. Might as well take advantage of the memory-management features that unique_ptr provides.

That was great until we tried to use the subsystem as a Requires() parameter. Requires() only accepts a Subsystem *. You can get around that with unique_ptr's get() method but the result is a bit messy:

Requires((Subsystem *)(examplesubsystem.get()));

If you use unique_ptr's across the board, you'll also run into the same issue with things like joystick buttons and anywhere else where you have to pass in a pointer to an object.

My questions are:
- Should we be using std::unique_ptr like the example code is leading us to do?
- Is FRC/WPILib moving towards using std::unique_ptr's?
- Will they overload existing methods to accept both types of pointers (old and new)?

Thanks in advance for any info you can provide.

jreneew2
15-11-2016, 12:18
Yes WPIlib is moving to using more of the standard library pointer wrappers. I like using them because it makes it way easier to manage the code. Also you don't have to cast to a subsystem pointer. We do


Requires(Robot::drivebaseSubsystem.get());

And it works fine for us.

I doubt that they will overload the functions to accept both. The whole reason they switched was to make it easier for teams to debug.

egaudet
15-11-2016, 12:58
Excellent. At least we're heading in the right direction.

I didn't realize that I didn't need the cast. I added it to fix an error but obviously it was some other problem that I was having. I just tried and it works fine without the cast.

Using the get() without all the extra parentheses makes it much more usable.

Thanks for the quick response.

connor.worley
19-11-2016, 15:39
Consider using https://google.github.io/styleguide/cppguide.html

calcmogul
29-11-2016, 03:20
We also started using smart pointers in WPILib so we could express ownership semantics. As the name implies, std::unique_ptr represents an object with one owner.

Since no one has mentioned this yet, I'll point out that a raw pointer is the non-owning counterpart of std::unique_ptr (which can be obtained via get()). Given those semantics, Requires() takes a non-owning reference to a subsystem because subsystem lifetime is a strict superset of command lifetime.

By the way, shared ownership is represented by std::shared_ptr and std::weak_ptr for owning and non-owning references respectively.