将不同大小的 C 数组传递给模板化函数,其中包含 2 个相同的参数

Passing C-arrays of different sizes to templated function taking 2 identical parameters

本文关键字:函数 包含 参数 数组      更新时间:2023-10-16

我有一个模板化函数,如下所示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
}

但是,我不确定如何实现它。欢迎任何想法。谢谢!

基于此答案的现场演示。

你需要

创建一个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])重载。

如果您不喜欢工厂函数方法,您也可以编写模板化(在N上)构造函数。

它可以代替任何标准容器,因为它支持begin/end操作。 它可以引用整个数组、数组的连续子集或任何标准容器的连续子序列。

以某种方式调用 f(const T&, const T&) 而不复制数组 元素

当然,这是行不通的,因为该模板函数返回两个相同类型的参数。

您需要做的是简单地将数组作为指针传递,并给出每个相应数组的大小。毕竟,关于数组,人们了解的第一件事是数组可以转换为指向数组第一个元素的指针。所以:

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

然后,您"真实"func()将知道每个数组的大小。

一种选择是使用转发引用:

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 样式数组。该参数是通过引用传递的,因此数组长度信息是可用的。

铌。请考虑在循环中使用auto&&auto const &,以避免复制容器中的元素。