patterncppMinor
Builder/named argument/fluent interface pattern with unique_ptr
Viewed 0 times
argumentbuilderwithnamedinterfacefluentunique_ptrpattern
Problem
I'm trying to figure out the cleanest way to implement a fluent interface with
```
#include
#include
#include
// Backported from C++14
namespace std
{
template
std::unique_ptr make_unique(Args &&... args)
{
return std::unique_ptr(new T(std::forward(args)...));
}
}
using namespace std;
class Widget
{
Widget() = delete;
Widget(Widget const &) = delete;
Widget(Widget &&) = delete;
Widget &operator=(Widget const &) = delete;
Widget &operator=(Widget &&) = delete;
public:
Widget(string const &name) :
m_name(name)
{ }
~Widget()
{ }
string const &name() const
{ return m_name; }
private:
string const m_name;
};
class WidgetBuilder
{
WidgetBuilder(WidgetBuilder const &) = delete;
WidgetBuilder(WidgetBuilder &&) = delete;
WidgetBuilder &operator=(WidgetBuilder const &) = delete;
WidgetBuilder &operator=(WidgetBuilder &&) = delete;
public:
WidgetBuilder()
{ }
~WidgetBuilder()
{ }
WidgetBuilder &name(string const &name)
{ m_name = name; return *this; }
unique_ptr create()
{ return make_unique(m_name); }
private:
string m_name;
};
class WidgetContainer
{
WidgetContainer() = delete;
WidgetContainer(WidgetContainer const &) = delete;
WidgetContainer(WidgetContainer &&) = delete;
WidgetContainer &operator=(WidgetContainer const &) = delete;
WidgetContainer &operator=(WidgetContainer &&) = delete;
public:
WidgetContainer(
string const &firstName,
string const &lastName,
unique_ptr>> widgets) :
m_firstName(firstName),
m_lastName(lastName),
m_widgets(move(widgets))
{ }
~WidgetContainer()
{ }
string const &firstName() const
{ return m_firstName; }
string const &lastName() const
{ return m_lastName; }
vector> const &widgets() const
{ return *m_widg
unique_ptr and other "modern" C++ language constructs. Here's my first attempt:```
#include
#include
#include
// Backported from C++14
namespace std
{
template
std::unique_ptr make_unique(Args &&... args)
{
return std::unique_ptr(new T(std::forward(args)...));
}
}
using namespace std;
class Widget
{
Widget() = delete;
Widget(Widget const &) = delete;
Widget(Widget &&) = delete;
Widget &operator=(Widget const &) = delete;
Widget &operator=(Widget &&) = delete;
public:
Widget(string const &name) :
m_name(name)
{ }
~Widget()
{ }
string const &name() const
{ return m_name; }
private:
string const m_name;
};
class WidgetBuilder
{
WidgetBuilder(WidgetBuilder const &) = delete;
WidgetBuilder(WidgetBuilder &&) = delete;
WidgetBuilder &operator=(WidgetBuilder const &) = delete;
WidgetBuilder &operator=(WidgetBuilder &&) = delete;
public:
WidgetBuilder()
{ }
~WidgetBuilder()
{ }
WidgetBuilder &name(string const &name)
{ m_name = name; return *this; }
unique_ptr create()
{ return make_unique(m_name); }
private:
string m_name;
};
class WidgetContainer
{
WidgetContainer() = delete;
WidgetContainer(WidgetContainer const &) = delete;
WidgetContainer(WidgetContainer &&) = delete;
WidgetContainer &operator=(WidgetContainer const &) = delete;
WidgetContainer &operator=(WidgetContainer &&) = delete;
public:
WidgetContainer(
string const &firstName,
string const &lastName,
unique_ptr>> widgets) :
m_firstName(firstName),
m_lastName(lastName),
m_widgets(move(widgets))
{ }
~WidgetContainer()
{ }
string const &firstName() const
{ return m_firstName; }
string const &lastName() const
{ return m_lastName; }
vector> const &widgets() const
{ return *m_widg
Solution
Please don't do this:
See: Why is “using namespace std;” considered bad practice?
I would change a couple of things:
In WidgetBuilder
I don't like the explicit call to
I would replace it with a conversion operator:
Then usage becomes:
In WidgetContainer
I don't see the need to put the
I would just do
Because of RVO and NRVO this is very efficient when returning objects. Also with the use of "Move Semantic" even passing it as a parameter is now very efficient.
In WidgetContainerBuilder
Like WidgetBuilder remove the
Not sure I would pass
using namespace std;See: Why is “using namespace std;” considered bad practice?
I would change a couple of things:
In WidgetBuilder
I don't like the explicit call to
create() WidgetBuilder.unique_ptr create()
{ return make_unique(m_name); }I would replace it with a conversion operator:
operator std::unique_ptr()
{ return std::make_unique(m_name);}Then usage becomes:
unique_ptr val = WidgetBuilder().name("Loki");In WidgetContainer
I don't see the need to put the
std::vector inside a std::uniqu_ptr.unique_ptr>> m_widgets;I would just do
std::vector>> m_widgets;Because of RVO and NRVO this is very efficient when returning objects. Also with the use of "Move Semantic" even passing it as a parameter is now very efficient.
In WidgetContainerBuilder
Like WidgetBuilder remove the
create() method.Not sure I would pass
WidgetBuilder to the addWidget() method. Why not a std::unique_ptr create them on the fly and use them as needed. (I suppose this is why you had an explicit create() method on Widget.WidgetContainerBuilder &addWidget(WidgetBuilder &widgetBuilder)Code Snippets
using namespace std;unique_ptr<Widget> create()
{ return make_unique<Widget>(m_name); }operator std::unique_ptr<Widget>()
{ return std::make_unique<Widget>(m_name);}unique_ptr<Widget> val = WidgetBuilder().name("Loki");unique_ptr<vector<unique_ptr<Widget>>> m_widgets;Context
StackExchange Code Review Q#56360, answer score: 3
Revisions (0)
No revisions yet.