有人可以解释一下这个给我数组大小的模板代码吗?

发布于 2024-07-11 20:36:12 字数 194 浏览 6 评论 0原文

template<typename T, size_t n>
size_t array_size(const T (&)[n])
{
    return n;
}

我没有得到的部分是这个模板函数的参数。 当我将数组传递到那里并给出 n 作为数组中元素的数量时,会发生什么?

template<typename T, size_t n>
size_t array_size(const T (&)[n])
{
    return n;
}

The part that I don't get is the parameters for this template function. What happens with the array when I pass it through there that gives n as the number of elements in the array?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

左耳近心 2024-07-18 20:36:12

好吧,首先您必须了解,尝试从数组中获取值可以为您提供指向其第一个元素的指针:

int a[] = {1, 2, 3};
int *ap = a; // a pointer, size is lost
int (&ar)[3] = a; // a reference to the array, size is not lost

引用使用其确切类型或其基类类型来引用对象。 关键是模板通过引用获取数组。 C++ 中不存在作为参数的数组(不是对它们的引用)。 如果你给一个参数一个数组类型,它将是一个指针。 因此,当我们想知道传递的数组的大小时,使用引用是必要的。 大小和元素类型是自动推导的,就像函数模板的通常情况一样。 使用我们之前定义的数组 a 调用的以下模板

template<typename T, size_t n>
size_t array_size(const T (&)[n]) {
    return n;
}

将隐式实例化以下函数:

size_t array_size(const int (&)[3]) {
    return 3;
}

可以像这样使用:

size_t size_of_a = array_size(a);

我不久前编写了一个变体[编辑:结果已经有人了此处]也有同样的想法可以在编译时确定一个值。 它不是直接返回值,而是根据 n 为模板提供返回类型:

template<typename T, size_t n>
char (& array_size(const T (&)[n]) )[n];

您说如果数组有 n 元素,则返回类型是对数组的引用具有大小n和元素类型char。 现在,您可以获得编译时确定的传递数组的大小:

size_t size_of_a = sizeof(array_size(a));

因为具有 n 元素的 char 数组的 sizeof n,因此也会给你给定数组中的元素数量。 在编译时,所以你可以这样做

int havingSameSize[sizeof(array_size(a))];

因为该函数从未被实际调用,所以不需要定义它,因此它没有函数体。 希望我能稍微澄清一下这个问题。

Well, first you have to understand that trying to get a value out of an array can give you a pointer to its first element:

int a[] = {1, 2, 3};
int *ap = a; // a pointer, size is lost
int (&ar)[3] = a; // a reference to the array, size is not lost

References refer to objects using their exact type or their base-class type. The key is that the template takes arrays by reference. Arrays (not references to them) as parameters do not exist in C++. If you give a parameter an array type, it will be a pointer instead. So using a reference is necessary when we want to know the size of the passed array. The size and the element type are automatically deduced, as is generally the case for function templates. The following template

template<typename T, size_t n>
size_t array_size(const T (&)[n]) {
    return n;
}

Called with our previously defined array a will implicitly instantiate the following function:

size_t array_size(const int (&)[3]) {
    return 3;
}

Which can be used like this:

size_t size_of_a = array_size(a);

There's a variation I made up some time ago [Edit: turns out someone already had that same idea here] which can determine a value at compile time. Instead of returning the value directly, it gives the template a return type depending on n:

template<typename T, size_t n>
char (& array_size(const T (&)[n]) )[n];

You say if the array has n elements, the return type is a reference to an array having size n and element type char. Now, you can get a compile-time determined size of the passed array:

size_t size_of_a = sizeof(array_size(a));

Because an array of char having n elements has sizeof n, that will give you the number of elements in the given array too. At compile time, so you can do

int havingSameSize[sizeof(array_size(a))];

Because the function never is actually called, it doesn't need to be defined, so it doesn't have a body. Hope I could clear the matter up a little bit.

梦途 2024-07-18 20:36:12

这样想,假设你有一堆函数:

// Note that you don't need to name the array, since you don't
// actually reference the parameter at all.
size_t array_size(const int (&)[1])
{
    return 1;
}

size_t array_size(const int (&)[2])
{
    return 2;
}

size_t array_size(const int (&)[3])
{
    return 3;
}
// etc...

现在当你调用这个函数时,哪个函数被调用?

int a[2];
array_size(a);  

现在,如果您模板化 arraysize,您会得到:

template <int n>
size_t array_size(const int (&)[n])
{
    return n;
}

编译器将尝试实例化与您调用它的任何参数相匹配的 array_size 版本。 因此,如果您使用 10 个整数的数组调用它,它将使用 n=10 实例化 array_size。

接下来,只需对类型进行模板化,这样您就可以不仅仅使用 int 数组来调用它:

template <typename T, int n>
size_t array_size(const T (&)[n])
{
    return n;
}

这样就完成了。

编辑:关于(&)的注释

& 周围需要括号,以区分 int 引用数组(非法)和引用整数数组(你想要的)。 由于 [] 的优先级高于 &,因此如果您有这样的声明:

const int &a[1];

由于运算符优先级,您最终会得到一个由 const 引用组成的单元素数组国际。 如果您希望首先应用 &,则需要使用括号强制执行:

const int (&a)[1];  

现在您有一个对单元素整数数组的 const 引用。 在函数参数列表中,如果不使用参数,则无需指定参数名称,因此可以删除名称,但保留括号:

size_t array_size(const int (&)[1])

Think of it this way, suppose you had a bunch of functions:

// Note that you don't need to name the array, since you don't
// actually reference the parameter at all.
size_t array_size(const int (&)[1])
{
    return 1;
}

size_t array_size(const int (&)[2])
{
    return 2;
}

size_t array_size(const int (&)[3])
{
    return 3;
}
// etc...

Now when you call this, which function gets called?

int a[2];
array_size(a);  

Now if you templatize the arraysize, you get:

template <int n>
size_t array_size(const int (&)[n])
{
    return n;
}

The compiler will attempt to instantiate a version of array_size that matches whatever parameter you call it with. So if you call it with an array of 10 ints, it will instantiate array_size with n=10.

Next, just templatize the type, so you can call it with more than just int arrays:

template <typename T, int n>
size_t array_size(const T (&)[n])
{
    return n;
}

And you're done.

Edit: A note about the (&)

The parentheses are needed around the & to differentiate between array of int references (illegal) and reference to array of ints (what you want). Since the precedence of [] is higher than &, if you have the declaration:

const int &a[1];

because of operator precedence, you end up with a one-element array of const references to int. If you want the & applied first, you need to force that with parentheses:

const int (&a)[1];  

Now the you have a const reference to a one element array of ints. In the function parameter list, you don't need to specify the name of a parameter if you don't use it, so you can drop the name, but keep the parentheses:

size_t array_size(const int (&)[1])
∝单色的世界 2024-07-18 20:36:12

数组没有任何反应。 它是一个未使用的参数,用于解析模板函数的签名。

它也不能用作模板参数,但这是一个单独的问题。

Nothing happens to the array. It's an unused parameter that is used to resolve the signature of the template function.

It also cannot be used as a template argument, but that's a separate nit.

ぃ双果 2024-07-18 20:36:12

对于我们这些没有“constexpr”的人来说,将结果作为编译时 const 得到的结果有点奇怪:

#include <iostream>

namespace
{

    template <size_t V>
    struct helper
    {
        enum
        {
            value = V
        };
    };


    template<typename T, size_t Size>
    auto get_size(T(&)[Size]) -> helper < Size >
    {
        return helper < Size >() ;
    }

    template<typename T>
    struct get_value
    {
        enum
        {
            value = T::value
        };
    };

}

int main()
{
    std::cout << get_value<decltype(get_size("Foo bar baz"))>::value;
}

A little weird way to get the result as compile-time const for those of us who don't have "constexpr":

#include <iostream>

namespace
{

    template <size_t V>
    struct helper
    {
        enum
        {
            value = V
        };
    };


    template<typename T, size_t Size>
    auto get_size(T(&)[Size]) -> helper < Size >
    {
        return helper < Size >() ;
    }

    template<typename T>
    struct get_value
    {
        enum
        {
            value = T::value
        };
    };

}

int main()
{
    std::cout << get_value<decltype(get_size("Foo bar baz"))>::value;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文