2017-07-19 199 views
1

我不確定標準允許我嘗試什麼,甚至可能沒有意義,所以通過一切手段隨時糾正我。使用可變參數類型參數的變量函數

我試圖將一個可變數量的std::function對象傳遞給接受可變參數的函數,並接受可變參數模板參數。模板參數指定返回類型中進行傳遞的功能函數的簽名看起來像這樣:

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

什麼我試圖做的是從每個funcs傳入的傳遞返回值到另一個以擴展價值形式接受它們的函數。例如。 std::make_shared<TType>(funcs()...);

我正在使用g ++ 7.1.1和--std=c++17標誌,導致編譯器發生故障。很明顯,它不應該排除故障,但是標準中是否有上述代碼無效的內容?或者,是否有不同的語法來完成這個目標?

爲了完整起見,這裏是一個最低限度的工作(對工作的一些定義)例如:

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

編輯,以顯示我原來的問題的更好的意圖

+0

你到底想幹什麼? – Justin

+0

如果編譯器出現故障,您可能需要提交錯誤報告。 – 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()...); 
} 

這是C++ 11 。這是低效的。

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

這足夠接近我需要的東西,請編輯C++ 17示例以使用'funcs()...'語法調用函數,我會接受。我編輯了原文,以更清楚地解釋我的意圖。 'CallFunctions'函數的主體然後變成'return std :: make_shared (funcs()...);'。我會接受這個答案,當它已被編輯 – Howard

+0

@howard我不認爲'funcs()...;'是有效的C++ 17;做了什麼改變?啊,我明白了,編輯的問題。 – Yakk

+0

我可以收集的最好的是,這個語法被參數包擴展所覆蓋:'pattern ....'如[這裏]概述的(http://en.cppreference.com/w/cpp/language/parameter_pack) – Howard

0

可以使用C++ 17 std::apply在參數數據包的每個元素上使用std::invoke。那麼你不再需要std::function了,因爲std::invoke只能調用可調用的對象,而且你不必再提供顯式的模板參數(反正它是反模式)。作爲獎勵,你甚至可以檢索被調用函數的返回值。

#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