2017-07-19 9 views
1

私が試していることが標準で許可されているかどうかわかりませんし、意味をなさないこともありますので、どうぞ私を修正してください。VariadicのVariadicタイプのパラメータのパラメータ

可変数の引数を受け付ける関数に可変数のstd::functionオブジェクトを渡そうとしています。また、可変のテンプレートパラメータも受け入れます。テンプレートパラメータは、渡された関数の戻り値の型を指定する関数のシグネチャはそうのようになります。私はしようとしてる何

template <typename ... TRets> 
void DoStuff(std::function<TRets...()> funcs...) 

は、渡されたfuncsのそれぞれからの戻り値を渡すですそれらを拡張された値の形式で受け入れる別の関数に渡します。例えば。 std::make_shared<TType>(funcs()...);

コンパイラにsegフォールトを引き起こす--std=c++17フラグを指定してg ++ 7.1.1を使用しています。明らかに、それはsegの誤りではありませんが、上記のコードが無効であることを標準で示していますか?または、おそらく、この目標を達成するための別の構文がありますか?

#include <functional> 
#include <memory> 

class MyClass { 
    public: 
     int m_a; 
     double m_b; 
     MyClass(int a, double b) : m_a(a), m_b(b) {}; 
}; 


template <typename TReturn, typename ... Args> 
std::shared_ptr<TReturn> CallFunctions(std::function<Args...()> funcs...) { 
    // Do stuff here 
    return std::make_shared<TReturn>(funcs()...); 
} 

int main(int argc, char * argv[]) { 
    auto x = CallFunctions<MyClass, int, double>(
     []() { return 5; }, 
     []() { return 3.14; } 
    ); 

    return 0; 
} 

編集これはC++ 11である私の元の質問

+0

何をしようとしていますか? – Justin

+0

コンパイラがsegfaultingの場合、バグレポートを提出することができます。 – Justin

+0

'CallFunctions'に渡されたすべての関数が引数を取らずに値を返すと思いますか? – Justin

答えて

2
template <class R, class... Args> 
std::shared_ptr<R> CallFunctions(std::function<Args()>... funcs) { 
    return std::make_shared<R>(funcs()...); 
} 

のよりよい意思を表示する:

完全を期すため、ここでの例(作業のいくつかの定義のための)最小限の作業であります。それは非効率的です。

template <class R, class... Args> 
auto CallFunctions(Args&&... funcs) 
-> decltype(std::make_shared<R>(funcs()...)) 
{ 
    return std::make_shared<R>(funcs()...); 
} 

不要なタイプの消去を取り除き、戻り値の型を明示的に渡す必要があります。

あなたは本当に戻り値の型を渡す場合:

template <class R, class... Args, class...Fs> 
auto CallFunctions(Fs&&... funcs) 
-> decltype(std::make_shared<R>(static_cast<Args>(funcs())...)) 
{ 
    return std::make_shared<R>(static_cast<Args>(funcs())...); 
} 

が、私は上記の第二ソリューションをやってお勧めします。

+0

これは私が必要とするものを得るのに十分近いので、 'funcs()...'構文を使って関数を呼び出すためのC++ 17の例を編集して受け入れます。元の投稿を編集して、自分の意図をより明確に説明しました。 'CallFunctions'関数の本体は' return std :: make_shared (funcs()...); 'になります。私はそれがそれに応じて編集されたときにこの回答を受け入れるでしょう – Howard

+0

@howard 'funcs()...;'は有効ではないと思ったC++ 17;何か変わった?ああ、私は、質問が編集されて参照してください。 – Yakk

+0

私が集めることができる最良のことは、この構文はパラメータパックの拡張でカバーされているということです: 'パターン....'概要[ここ](http://en.cppreference.com/w/cpp/language/parameter_pack) – Howard

0

パラメータパックの各要素にstd::invokeを使用するには、C++ 17 std::applyを使用できます。 std::invokeは呼び出し可能なオブジェクトだけを呼び出すことができ、明示的なテンプレート引数をもはや与える必要がないので(これはアンチパターンです)、std::functionはもう必要ありません。ボーナスとして、呼び出された関数の戻り値を取得することさえできます。

#include <functional> 
#include <iostream> 
#include <memory> 
#include <tuple> 

template < typename... R, typename... Args > 
auto CallFunctions(Args... funcs) { 
    // Do stuff here 
    return std::apply(
    [] (auto&&... x) { 
     return std::make_tuple(std::make_shared<R>(std::invoke(x))...); 
    }, std::make_tuple(funcs...) 
    ); 
} 

int main() { 
    auto r = CallFunctions<int,double>(
     []() { return 5; }, 
     []() { return 3.14; } 
    ); 

    std::cout << *std::get<0>(r) << ' ' << *std::get<1>(r) << '\n'; 

    return 0; 
} 

Live example

関連する問題