2017-09-14 114 views
7

嘗試針對該類的特定構造函數的特定類類型嘗試別名make_shared。我最好的嘗試:Constexpr重載模板函數的別名

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

產量:

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>); 

我在做什麼錯?

回答

4

std::make_shared可變參數函數模板。您只指定<foo>作爲模板參數,但您還需要在其中的某個地方使用int。無論如何,你的方法肯定會失敗,因爲它依賴於如何佈置make_shared的模板參數,並且因爲在C++中使用重載集合通常很麻煩。

我建議什麼是創建一個包裝函數:

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

在我看來,這是比較容易寫,閱讀和理解。如果你真的需要 SFINAE友好和noexcept,你可以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); } 

宏可以用來作出上述聲明的痛苦。


如果你真的想要一個函數指針,這似乎工作:

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

make_shared的聲明:

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

您需要提供T=foo和東西Args... 。由於Args...是轉發參考包,它總是會推斷爲左值引用右值引用。這就是爲什麼<foo, const int&>是一組有效的模板參數,而<foo, int>則不是。

由於Zefick在評論中指出,所有這一切都可以簡化爲:

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

是不是真的在這裏所需要的演員。

+1

+1,但是你應該在你的「如果你真的想要」例子中使用'const int&'而不是'int &&'。就像,'const int i = 42; auto f = newfoo(i);'不起作用。 –

+0

@MilesBudnek:好點,改變我的回答 –

+2

'constexpr auto newfoo = std :: make_shared '只是工作。爲什麼我們需要演員? – Zefick