2017-09-14 4 views
7

Der Versuch, make_shared für einen bestimmten Konstruktor dieser Klasse in einen bestimmten Klassentyp umzuwandeln. Mein bester Versuch:Constexpr Alias ​​der überladenen Vorlagefunktion

class foo { public: foo(int x) : y(x) {} int y; }; 
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>); 

Ausbeuten:

error: invalid static_cast from type ‘<unresolved overloaded function type>’ to type ‘std::shared_ptr<foo> (*)(int)’ 
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>); 

Was mache ich falsch?

Antwort

4

std::make_shared ist eine variadic Funktion Vorlage. Sie geben nur <foo> als Vorlage-Parameter an, aber Sie benötigen auch eine int irgendwo dort. Unabhängig davon ist Ihr Ansatz zwangsläufig fehlgeschlagen, da es darauf angewiesen ist, wie die Vorlagenargumente von make_shared angelegt wurden und es im Allgemeinen umständlich ist, mit Überladungssätzen in C++ zu arbeiten.

Was ich vorschlagen, ist eine Wrapper-Funktion zu erstellen, anstatt:

constexpr auto newfoo(int x) 
{ 
    return std::make_shared<foo>(x); 
} 

Meiner Meinung nach ist es einfacher zu schreiben, lesen und zu verstehen. Wenn Sie wirklich brauchen SFINAE Freundlichkeit und noexcept, können Sie repeat the body three times:

constexpr auto newfoo(int x) 
    ->   decltype(std::make_shared<foo>(x)) 
     noexcept(noexcept(std::make_shared<foo>(x))) 
     {   return std::make_shared<foo>(x); } 

Ein Makro verwendet werden, kann die obige Erklärung weniger schmerzhaft zu machen.


Wenn Sie wirklich einen Funktionszeiger wollen, scheint dies zu funktionieren:

auto newfoo = 
    static_cast<std::shared_ptr<foo>(*)(const int&)>(
     &std::make_shared<foo, const int&>); 

Blick auf make_shared ‚s Erklärung:

template< class T, class... Args > 
shared_ptr<T> make_shared(Args&&... args); 

Sie benötigen T=foo und etwas für Args... liefern . Da Args... ein Forwarding-Referenzpaket ist, wird es immer entweder auf lvalue-Referenzen oder rvalue-Referenzen schließen. Deshalb ist <foo, const int&> ein gültiger Satz von Vorlagenparametern und <foo, int> ist nicht.

constexpr auto newfoo = &std::make_shared<foo, const int&>; 

Die Besetzung hier nicht wirklich gebraucht wird:

Wie Zefick in den Kommentaren darauf hingewiesen, all dies kann vereinfacht werden.

+1

+1, aber Sie sollten wahrscheinlich 'const int &' anstelle von 'int &&' in Ihrem "Wenn Sie wirklich wollen" Beispiel verwenden. Wie es ist, const int i = 42; auto f = newfoo (i); 'wird nicht funktionieren. –

+0

@MilesBudnek: guter Punkt, änderte meine Antwort –

+2

'constexpr auto newfoo = std :: make_shared ' funktioniert einfach. Warum brauchen wir die Besetzung? – Zefick

Verwandte Themen