2016-01-20 77 views
4

我目前正在使用std::bind從函數模板的std ::綁定和函數模板

template<class Iterator> 
void printRange(Iterator first, Iterator last) { 
    std::copy(first, last, std::ostream_iterator<typename Iterator::value_type>(std::cout, " ")); 
    std::cout << std::endl; 
} 

概念創建std::function<void()>,我要的是

int main() { 
    std::vector<int> v{1, 2, 3}; 
    auto f0 = std::bind(printRange, v.begin(), v.end()); // won't compile, of course 
    f0(); 
    return 0; 
} 

我明白,這不不能編譯,我必須在實際使用之前實例化函數模板。例如,下面的方案將工作:

auto f1 = std::bind(printRange<std::vector<int>::const_iterator>, v.begin(), v.end()); 
auto f2 = std::bind(printRange<decltype(v.begin())>, v.begin(), v.end()); 
auto f3 = [&v]() { printRange(v.begin(), v.end()); }; 

我已經創建了一個方便的功能

template<class Iterator> 
std::function<void()> makePrintRangeFunction(Iterator first, Iterator last) { 
    return std::bind(printRange<Iterator>, first, last); 
} 

緩解過程:

auto f4 = makePrintRangeFunction(v.begin(), v.end()); 

我不知道是否有可能創建一個更通用的std::function<void()>生成器,接受函數模板作爲第一個參數,函數模板參數作爲可變長度參數列表?如果不使用內置的語言功能,可能通過宏?

+2

和拉姆達是不能接受的? – TemplateRex

+0

是的,我發現lambda更容易編碼和讀取所有需要過去綁定的東西。 –

+0

@TemplateRex:在這種情況下,lambda可以,但是一旦我需要俘獲不止一個變量,我認爲'std :: bind'會導致一個更具可讀性的表達式。 – Marcel

回答

3

由於隆特因爲你不需要有模板函數的返回類型,你可以這樣做:

#include <functional> 
#include <iostream> 
#include <typeinfo> 


template<typename ... T> 
std::function<void()> makePrintRangeFunction(void (*f)(T...), T... param) { 
    return std::bind(f, param...); 
} 

template<typename T, typename V> 
void print(T type, V val) 
{ 
    std::cout << typeid(type).name() << '\n' << val << '\n'; 
} 

int main() 
{ 
    int i = 5; 
    double d = 10.5; 
    auto f = makePrintRangeFunction(print, i, d); 
    f(); 
} 
+0

這正是我所期待的!非常感謝你! – Marcel

1

如果你的編譯器支持C++ 14,你可以定義一個通用的λ包裝爲:

template<typename F> 
auto fungen(F f) { 
    return [=](auto... args) { f(args...); }; 
} 

使用案例:

int main() { 
    std::vector<int> v {1, 2, 3, 4}; 
    auto f = fungen(printRange<std::vector<int>::iterator>); 
    f(v.begin(), v.end()); 
} 

Live Demo

+0

我真的不是你的解決方案不同於'auto f1 = std :: bind(printRange :: const_iterator>,v.begin(),v.end());'或者我是遺漏了什麼? – Marcel

+0

看來,OP希望編譯器從函數參數中推導出模板參數。用例:'auto f = fungen(printRange,v.begin(),v.end());'。令人遺憾的是,模板模板只能與類類型一起工作,而我並沒有看到在這種情況下是否有可能扭曲模板參數推演。 –

+0

@Revolver_Ocelot:...如果我使用類類型,我將不得不使模板參數再次明確,對吧? – Marcel

1

也許下面的代碼將有所幫助: )

template <class F, class... Args> 
void test(F&& f, Args&&... args) { 
std::function<typename std::result_of<F(Args...)>::type()> task(
    std::bind(std::forward<F>(f), std::forward<Args>(args)...)); 
    task(); 
} 
+0

哦,我不明白,我想第二個答案是你想要的。 – Tommy