2017-09-14 14 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); } 

マクロは上記の宣言は、苦痛が少ないために使用することができます。


あなたが本当に関数ポインタをしたい場合は、これが動作しているようです:make_sharedの宣言で

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

ルック:

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

あなたはArgs...ためT=fooと何かを提供する必要があります。 Args...は転送参照パックであるため、左値参照またはの値の参照に常に推算されます。このため、<foo, const int&>はテンプレートパラメータの有効なセットであり、<foo, int>は有効ではありません。

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

キャストが本当にここに必要とされていません:コメントで指摘

Zefickとして、このすべてはに単純化することができます。

+1

+1ですが、 "本当にしたい場合"の例では 'int &&'の代わりに 'const int&'を使うべきでしょう。つまり、 'const int i = 42; auto f = newfoo(i); 'は動作しません。 –

+0

@MilesBudnek:良い点、私の答えを変更しました –

+2

'constexpr auto newfoo = std :: make_shared 'が動作します。なぜキャストが必要なの? – Zefick

関連する問題