如何让std :: make_unique成为我班级的朋友

时间:2015-11-24 22:24:52

标签: c++ templates c++14 unique-ptr friend-function

我想将std::make_unique函数声明为我班级的朋友。原因是我想声明我的构造函数protected并提供使用unique_ptr创建对象的替代方法。以下是示例代码:

#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;
}

现在我收到此错误:

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

std::make_unique声明为班级朋友的正确方法是什么?

1 个答案:

答案 0 :(得分:19)

make_unique完美地转发你传递给它的论据;在您的示例中,您将左值(x)传递给函数,因此它将参数类型推导为int&。您的friend函数声明需要

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

同样,如果您move(x)CreateA friendfriend std::unique_ptr<A> std::make_unique<A>(T&&); 声明需要

make_unique

这将得到compile的代码,但绝不保证它会在另一个实现上编译,因为你知道,friend将其参数转发给另一个内部帮助器实际实例化你的类的函数,在这种情况下,帮助器需要是import matplotlib import matplotlib.pyplot as plt import random fig = plt.figure() ax = fig.add_subplot(111, aspect='equal') plt.xlim([0, 1001]) plt.ylim([0, 1001]) n=10000 for i in range(0,n): x = random.uniform(1, 1000) y = random.uniform(1, 1000) ax.add_patch(matplotlib.patches.Rectangle((x, y),1,1,)) plt.show()