我有一个模板化函数func
如下所示,它接受两个相同类型的参数(通常是两个相同类型但不同大小的STL容器)。我想让它与相同类型但不同大小的的C数组一起工作。
template<class T>
void func(const T& a, const T& b) {
// some code like as follows
for(auto x : a) {
cout << x << " ";
}
cout << endl;
for(auto x : b) {
cout << x << " ";
}
}
显然,以下代码失败了error: no matching function for call to 'func(int [2], int [3])'
:
int a1[] = {1, 2};
int a2[] = {3, 4, 5};
func(a1, a2);
我无法改变功能签名,但我可以重载它。我也想避免不必要的副本。我的尝试是写一个像:
这样的重载template<class T, size_t M, size_t N>
void func(const T (&a)[M], const T (&b)[N]) {
//somehow calling f<T>(const T&, const T&) without copying array elements
}
但是,我不确定如何实现它。欢迎任何想法。谢谢!
根据demo直播this answer。
答案 0 :(得分:2)
您需要创建一个range<T*>
结构来包装数组,并为其定义begin()
和end()
函数。
可以像
一样简单template<typename Iterator>
struct range { Iterator begin_, end_; };
template<typename T>
T begin(const range<T>& ar) { return ar.begin_; }
template<typename T>
T end(const range<T>& ar) { return ar.end_; }
template<typename T, size_t N>
range<T*> make_array_range(T (&array)[N])
{
using std::begin; using std::end;
return { begin(array), end(array) };
}
func( make_array_range(a1), make_array_range(a2) );
然后,您可以使用此构建块轻松编写func(T[N], T[M])
重载。
如果您不喜欢工厂函数方法,也可以编写模板化(on N
)构造函数。
它可以用来代替任何标准容器,因为它支持begin
/ end
操作。它可以引用整个数组,数组的连续子集,或任何标准容器的连续子序列。
答案 1 :(得分:0)
以某种方式调用f(const T&amp;,const T&amp;)而不复制数组 元素
当然,由于该模板函数返回两个相同类型的参数,因此无法工作。
做 需要做的是简单地将数组作为指针传递,并给出每个相应数组的大小。毕竟,学习数组的第一件事是数组可以转换为指向数组第一个元素的指针。这样:
template<class T>
void func(const T *a, const T *b, size_t a_size, size_t b_size) {
// ...
}
现在,你的
template<class T, size_t M, size_t N>
void func(const T (&a)[M], const T (&b)[N])
应该可以简单地做这样的事情:
func(&a[0], &b[0], M, N);
你&#34;真实&#34;然后func()
将知道每个数组的大小。
答案 2 :(得分:0)
一种选择是使用转发参考:
template<class T, class U>
void func(T&& a, U&& b)
{
for(auto x : a)
cout << x << " ";
cout << endl;
for(auto x : b)
cout << x << " ";
}
然后你可以传递你的其他容器或你的C风格的数组。参数通过引用传递,因此数组长度信息可用。
NB。考虑在循环中使用auto&&
或auto const &
,以避免在容器中复制元素。