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

The*_*ter 27 c++ templates unique-ptr friend-function c++14

我想声明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;
}
Run Code Online (Sandbox Code Playgroud)

现在我收到此错误:

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
Run Code Online (Sandbox Code Playgroud)

宣布std::make_unique成为班上朋友的正确方法是什么?

Pra*_*ian 19

make_unique完美转发你传递给它的论据; 在你的例子中,你将lvalue(x)传递给函数,因此它会将参数类型推断为int&.你的friend函数声明需要

friend std::unique_ptr<A> std::make_unique<A>(T&);
Run Code Online (Sandbox Code Playgroud)

同样,如果你move(x)在内CreateA,friend声明就需要

friend std::unique_ptr<A> std::make_unique<A>(T&&);
Run Code Online (Sandbox Code Playgroud)

这将获得编译的代码,但绝不保证它将在另一个实现上编译,因为你所知道的,make_unique将它的参数转发给另一个实际实例化你的类的内部帮助函数,在这种情况下帮助器需要是一个friend.

  • @TheCrafter我认为你必须与相应的`make_unique`签名成为朋友,我认为你不会更通用,因为不允许对函数模板进行部分特化.我的建议是忘记`make_unique`并让`CreateA`返回`unique_ptr <A>(new A(...))`.与`make_shared`不同,`make_unique`并没有给你带来很多好处. (4认同)