【问题标题】:Template of array of function pointers函数指针数组模板
【发布时间】:2015-03-17 18:25:39
【问题描述】:

我有一些函数,其中一些是重载的,有些是模板,例如:

void fun1 (vector<string> &a, int b);
void fun1 (vector<double> &a, int b);

template <typename t>
void fun2 (t a[], int b);

等等。我使用的每个函数都有 2 种数据类型的版本,一种是数组,另一种是向量(字符串向量、双精度向量、字符串数组和双精度数组)。问题是,我可以为指针数组创建一个模板吗?除了:

void (*strvecfun[])(vector <string>&, long, long)={fun1, fun2};
void (*dblvecfun[])(vector <double>&, long, long)={fun1, fun2};
void (*strarrfun[])(string [], long, long)={fun1, fun2};

等等?

【问题讨论】:

  • vector &lt;string&gt; a&amp; 这是一种新语法,或者可能是错字;)。 [postreference]。您实际上是在编辑这些函数中vectors 的长度吗?或者你只是在编辑元素?如果你不需要 2 个重载怎么办?
  • 肯定是错字,抱歉 ;) 不,没有长度编辑,所有功能都是排序功能。

标签: c++ arrays templates pointers


【解决方案1】:

你可以使用

template<typename Func>
struct func_array {
  static Func *const data[];
};

template<typename Func>
Func *const func_array<Func>::data[] = { fun1, fun2 };

稍后再调用

func_array<void(std::vector<double>&, long, long)>::data[0](dvec, l1, l2);
func_array<void(std::vector<string>&, long, long)>::data[1](svec, l1, l2);
// ...and so forth

这自然要求您将要使用的所有签名与您放入列表中的所有函数都有匹配的重载。

【讨论】:

  • 这是我一直在寻找的东西。有什么办法可以缩短通话时间吗?
  • 好吧,你可以说auto &amp;foo = func_array&lt;void(std::vector&lt;double&amp;&gt;, long, long)&gt;::data;,然后打电话给foo[0](dvec, l1, l2);左右。还有using 声明。不过,您必须在某个时候解析函数类型,这样就可以做到最好了。
  • 太好了,非常感谢。对我的需要来说已经绰绰有余了
  • 哦,还有一件事——我怎样才能将它传递给一个接受指针数组作为参数的函数?到目前为止,我已经被教导使用 void function(void (*fun[])(vector &lt;string&gt;&amp;, long), vector &lt;string&gt; &amp;tab, long n) 例如
  • 通过上面的实现,你可以写一个函数void foo(void(*const arr[])(std::vector&lt;double&gt;&amp;, long, long));并调用foo(func_array&lt;void(std::vector&lt;double&gt;&amp;, long, long&gt;::data);。而且总是有decltype,如果你在那个时候设置了一个别名(否则它不会让事情变得更清楚)。
【解决方案2】:

不要有两种实现,而是一种。让您的数据采用array_view&lt;double&gt;

template<class T>
struct array_view {
  // can make this private:
  T* b = 0; T* e = 0;

  // core methods:
  T* begin() const { return b; }
  T* end() const { return e; }

  // utility methods:
  size_t size() const { return end()-begin(); }
  T& front() const { return *begin(); }
  T& back() const { return *std::prev(end()); }
  bool empty() const { return begin()==end(); }

  // core ctors:
  array_view(T* s, T* f):b(s),e(f) {};
  array_view()=default;
  array_view(array_view const&)=default;

  // derived ctors:
  array-view(T* s, size_t l):array_view(s, s+l) {};
  template<size_t N>
  array_view( T(&arr)[N] ):array_view(arr, N) {};
  template<size_t N>
  array_view( std::array<T,N>&arr ):array_view(arr.data(), N) {};
  template<class A>
  array_view( std::vector<T,A>& v ):array_view(v.data(), v.size()) {};

  // extra ctors that fail to compile if `T` is not const, but
  // are mostly harmless even if `T` is not const, and useful if
  // `T` is const.  We could do fancy work to disable them, but
  // I am lazy:
  using non_const_T = std::remove_const_t<T>;
  template<class A>
  array_view( std::vector<non_const_T,A>const& v ):array_view(v.data(), v.size()) {};
  template<size_t N>
  array_view( std::array<non_const_T,N>const&arr ):array_view(arr.data(), N) {};
  array_view( std::initializer_list<non_const_T> il ):array_view(il.data(), il.size()) {};
};

array_view 就像一个容器中的视图,可以从多个 std 容器以及原始数组隐式转换。

void fun1 (array_view<std::string> a);

a.size() 告诉你它有多长,甚至可以在for(:) 循环中迭代。

std::vector&lt;T&gt;&amp; 远比你需要的强大。通过使用array_view,我们只公开您需要的内容(访问元素),因此能够同时获取数组和容器。

如果你传入一个“真正的”C 风格的数组,它会自动推导出长度。如果您改为传入一个指针(或 [] 真正的指针数组),您还必须像这样传递长度:

fun1( {ptr, length} );

【讨论】:

    【解决方案3】:

    创建一个名为 max 的函数,它将返回数组中最大元素的值。

    函数的参数应该是数组大小的地址。

    将此函数制作成一个模板,以便它可以处理任何数值类型的数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      • 1970-01-01
      相关资源
      最近更新 更多