Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make std::make_unique a friend of my class

I want to declare std::make_unique function as a friend of my class. The reason is that I want to declare my constructor protected and provide an alternative method of creating the object using unique_ptr. Here is a sample code:

#include <memory>  template <typename T> class A { public:     // Somehow I want to declare make_unique as a friend     friend std::unique_ptr<A<T>> std::make_unique<A<T>>();       static std::unique_ptr<A> CreateA(T x)     {         //return std::unique_ptr<A>(new A(x)); // works         return std::make_unique<A>(x);         // doesn't work     }  protected:     A(T x) { (void)x; } };  int main() {     std::unique_ptr<A<int>> a = A<int>::CreateA(5);     (void)a;     return 0; } 

Right now I get this error:

Start In file included from prog.cc:1: /usr/local/libcxx-head/include/c++/v1/memory:3152:32: error: calling a protected constructor of class 'A<int>' return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...));                            ^ prog.cc:13:21: note: in instantiation of function template specialization 'std::__1::make_unique<A<int>, int &>' requested here     return std::make_unique<A>(x);     // doesn't work                 ^ prog.cc:22:41: note: in instantiation of member function 'A<int>::CreateA' requested here std::unique_ptr<A<int>> a = A<int>::CreateA(5);                                     ^ prog.cc:17:5: note: declared protected here A(T x) { (void)x; } ^ 1 error generated. 1 Finish 

What is the correct way to declare std::make_unique as a friend of my class?

like image 995
TheCrafter Avatar asked Nov 24 '15 22:11

TheCrafter


People also ask

Does make_unique throw?

A little late, but make_unique can itself throw according to cppreference: make_unique "may throw std::bad_alloc or any exception thrown by the constructor of T.

What does std:: make_ unique do?

make_unique prevents the unspecified-evaluation-order leak triggered by expressions like foo(unique_ptr<X>(new X), unique_ptr<Y>(new Y)) . (Following the advice "never say new " is simpler than "never say new , unless you immediately give it to a named unique_ptr ".)

What is a unique_ptr?

(since C++11) std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.

How do you create a unique pointer in C++?

auto ptr = make_unique<int>(); // Create a new unique_ptr object. auto ptr = make_unique<int>(); The dynamically allocated object is destroyed when the created unique pointer object is destroyed.


1 Answers

make_unique perfect forwards the arguments you pass to it; in your example you're passing an lvalue (x) to the function, so it'll deduce the argument type as int&. Your friend function declaration needs to be

friend std::unique_ptr<A> std::make_unique<A>(T&); 

Similarly, if you were to move(x) within CreateA, the friend declaration would need to be

friend std::unique_ptr<A> std::make_unique<A>(T&&); 

This will get the code to compile, but is in no way a guarantee that it'll compile on another implementation because for all you know, make_unique forwards its arguments to another internal helper function that actually instantiates your class, in which case the helper would need to be a friend.

like image 149
Praetorian Avatar answered Oct 14 '22 10:10

Praetorian