2013-05-13 43 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