2015-11-24 8 views
21

Ich möchte std::make_unique als ein Freund meiner Klasse zu erklären. Der Grund ist, dass ich meinen Konstruktor protected deklarieren und eine alternative Methode zum Erstellen des Objekts mit unique_ptr bereitstellen möchte. Hier ist ein Beispielcode:Wie man std :: make_unique ein Freund meiner Klasse macht

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

Im Moment bekomme ich diesen Fehler:

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 

Was ist der richtige Weg std::make_unique als Freund meiner Klasse zu erklären?

+0

versuchen, kompilieren mit klingeln - es klagt: 'main.cpp: 17: 39: fehler: freunde können nur klassen oder funktionen sein - friend' std :: unique_ptr > std :: make_unique >(); 'mit der Fehlerort ist die Template Instanziierung. – marko

+0

Interessanterweise Compiler mit -std = C++ 14 und dieser verschwindet, und die Fehler deuten auf @ Praetorian Antwort unten. – marko

+0

@marko Der obige Fehler ist mit clang. Ich bin jetzt auf MSVC (vs 2013) jetzt. Funktioniert dort auch nicht. – TheCrafter

Antwort

16

make_unique perfekt leitet die Argumente weiter, die Sie ihm übergeben; In Ihrem Beispiel übergeben Sie einen Lvalue (x) an die Funktion, damit der Argumenttyp als int& abgeleitet wird. Ihre friend Funktionsdeklaration

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

ähnlich sein muss, wenn man move(x) innerhalb CreateA ist, die friend Erklärung würde

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

Diese erhalten den Code compile, sein muß, ist aber in keinem Weg eine Garantie, dass es auf einer anderen Implementierung kompilieren wird, denn für alles, das Sie wissen, leitet make_unique seine Argumente zu einer anderen internen Helferfunktion weiter, die Ihre Klasse tatsächlich instanziiert, in welchem ​​Fall der Helfer einesein müsste.

+0

In der Tat, das funktioniert! Was aber, wenn ich meinem Konstruktor mehr Argumente übergeben möchte? Wenn mein Konstruktor zum Beispiel 'A (const std :: string & str1, const std :: shared_ptr & ptr1) ist, ist das komplexer als eine ganze Zahl. – TheCrafter

+2

@TheCrafter Ich denke, Sie müssen sich mit der entsprechenden 'make_unique'-Signatur anfreunden, ich glaube nicht, dass Sie allgemeiner werden, weil eine teilweise Spezialisierung von Funktionsvorlagen nicht erlaubt ist. Mein Vorschlag ist es, 'make_unique' zu ​​vergessen und' CreateA' return 'unique_ptr (new A (...))' zu haben. Im Gegensatz zu 'make_shared' kauft' make_unique' nicht viele Vorteile. – Praetorian

+0

Ok, ich habe es. Ich wollte nur wissen, ob es einen Workaround gibt !!Danke für deine Antwort :) – TheCrafter