2013-05-13 91 views
1

我想實現這樣的事情:調用(回調)的模板類模板參數

template<class IT> 
size_t foo(IT begin,IT end) {return end-begin;} 

template<template (class) class FOO> 
class BAR 
{ 
    public: 
    any_container<any_type> container; 
    size_t call_foo 
    { 
    FOO<any_container<any_type>::iterator>(container.begin(), container.end()); 
    } 
}; 

此外,我希望能夠傳遞功能,拉姆達或函數對象爲FOO。 這裏應該使用std::function,但不可能用任意類型T來聲明std::function<size_t(T,T)>。 我絕對不想在模板BAR參數列表中指定內容器或其迭代器的類型。

有什麼辦法可以用優雅的方式解決這個問題嗎?基於您的評論

+0

你知道的std ::'開始'和'std :: end'? – 2013-05-13 10:58:50

+0

在你的例子中'foo()'的目的是什麼?什麼是'any_container'? – 2013-05-13 11:09:28

+0

BAR是通用協議實現,foo是系統相關的低層發送或接收實現。 std :: begin和end如何提供幫助? – ardabro 2013-05-13 11:18:40

回答

0

我認爲你正在尋找的東西是這樣的:

#include <algorithm> 
#include <iostream> 
#include <iterator> 
#include <utility> 
#include <vector> 

struct Sender { 

    template<typename Iter> 
    std::size_t operator()(Iter begin, Iter end) { 
    for(Iter cur = begin; cur != end; ++cur) { 
     // your low-level send stuff 
    } 
    return (end - begin); 
    } 
}; 

struct Receiver { 

    template<typename Iter> 
    std::size_t operator()(Iter begin, Iter end) { 
    for(Iter cur = begin; cur != end; ++cur) { 
     // your low-level receive stuff 
    } 
    return (end - begin); 
    } 
}; 

template<typename Fn> 
struct Bar 
{ 
protected: 
    Fn _fn; 
public: 
    Bar(Fn fn) : _fn(std::move(fn)) { } 

    template<typename Container> 
    std::size_t call_fn(Container & container) 
    { 
    return _fn(std::begin(container), std::end(container)); 
    } 
}; 

template<typename Fn> 
auto create_bar(Fn && fn) -> Bar<typename std::remove_reference<Fn>::type> { 
    return { std::forward<Fn>(fn) }; 
} 

用法很簡單:

template<typename Iter> 
std::size_t my_foo(Iter begin, Iter end) { 
    return (end - begin); 
} 

int main(int argc, char ** argv) { 
    typedef typename std::vector<int>::iterator iter; 
    // functors 
    auto functor = create_bar(Sender()); 
    // lambdas 
    auto lambda = create_bar([](iter begin, iter end) -> std::size_t { return (end - begin); }); 
    // plain old functions 
    auto function = create_bar(&my_foo<iter>); 

    std::vector<int> tmp = { 0, 1, 2, 5}; 

    std::cout << "Functor: " << functor.call_fn(tmp) << std::endl; 
    std::cout << "Lambda: " << lambda.call_fn(tmp) << std::endl; 
    std::cout << "Function: " << function.call_fn(tmp) << std::endl; 

    return 0; 
} 

活生生的例子here

+0

看起來幾乎沒問題,但是你必須聲明它以便與lambda或函數一起使用。另一方面:你聲明的包裝類有點複雜。我仍然希望能夠更純粹地制定解決方案。 – ardabro 2013-05-13 12:23:52