【问题标题】:template of callable (callback) as class template parameter可调用(回调)的模板作为类模板参数
【发布时间】:2013-05-07 09:15:01
【问题描述】:

我想实现这样的目标:

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());
  }
};

此外,我希望能够将函数、lambda 或函数对象作为FOO 传递。 可能std::function 应该在这里使用,但不可能用任意类型T 声明std::function&lt;size_t(T,T)&gt;。 而且我绝对不想在模板 BAR 参数列表上指定内部容器的类型或其迭代器。

有什么方法可以优雅地解决这个问题吗?

【问题讨论】:

  • 你知道std::beginstd::end吗?
  • 您的示例中foo() 的目的是什么? any_container 是什么?
  • BAR 是通用协议实现,而 foo 是系统相关的低级发送或接收实现。 std::begin 和 end 有什么帮助?

标签: c++ templates c++11 generic-programming


【解决方案1】:

根据您的评论,我认为您正在寻找这样的东西:

#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

【讨论】:

  • 看起来几乎没问题,但是您必须声明 iter 才能与 lambda 或函数一起使用。另一方面:您正在声明包装类,这有点复杂。我仍然希望可以使解决方案更纯粹。
猜你喜欢
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多