函数指针数组模板
Template of array of function pointers
我有几个函数,其中一些是重载的,一些是模板,例如:
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};
等等?
您可以使用
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
自然地,这要求您要使用的所有函数的所有签名都有匹配的重载。
与其拥有 2 个实现,不如拥有一个。让您的数据采用 array_view<double>
:
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<T>&
比您需要的要强大得多。通过使用 array_view
,我们只公开您需要的内容(访问元素),因此能够同时使用数组和容器。
如果您传入 "real" C 样式数组,它会自动推断长度。如果你改为传入一个指针(或 []
真正的指针数组),你还必须传递长度,如:
fun1( {ptr, length} );
创建一个名为 max 的函数,它将 return 数组中最大元素的值。
函数的参数应该是数组大小的地址。
将此函数制作成模板,以便它可以处理任何数值类型的数组。
我有几个函数,其中一些是重载的,一些是模板,例如:
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};
等等?
您可以使用
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
自然地,这要求您要使用的所有函数的所有签名都有匹配的重载。
与其拥有 2 个实现,不如拥有一个。让您的数据采用 array_view<double>
:
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<T>&
比您需要的要强大得多。通过使用 array_view
,我们只公开您需要的内容(访问元素),因此能够同时使用数组和容器。
如果您传入 "real" C 样式数组,它会自动推断长度。如果你改为传入一个指针(或 []
真正的指针数组),你还必须传递长度,如:
fun1( {ptr, length} );
创建一个名为 max 的函数,它将 return 数组中最大元素的值。
函数的参数应该是数组大小的地址。
将此函数制作成模板,以便它可以处理任何数值类型的数组。