简体   繁体   English

检查给定std :: array编译时的元素数

[英]Check number of elements given to std::array compile time

I have a performance critical code where I query N indices. 我有一个性能关键代码,我查询N个索引。 How can I check compile-time with a static_assert whether exactly N indices are given, without sacrificing performance? 如何在不牺牲性能的情况下使用static_assert检查编译时是否给出了N个索引?

#include <array>

template<int N>
void test(const std::array<int, N>& indices)
{
    // static_assert:  has three elements.
    return;
}

int main()
{
    test<3>({1, 2, 3}); // OK
    test<3>({1, 2});    // Needs to crash, because 2 < 3

    test<2>({1, 2, 3}); // Crashes, because 3 > 2
    test<2>({1, 2});    // OK

    return 0;
}

How can I check compile-time with a static_assert whether three indices are given 如何使用static_assert检查编译时是否给出了三个索引

You can't. 你不能。 They array is of size 3 so it will always have 3 elements. 它们的数组大小为3,因此它总是有3个元素。 When you do something like 当你做类似的事情

test({1, 2}); 

The array initializes the first two elements with 1 and 2 and then zero-initializes the last element. 数组使用12初始化前两个元素,然后对最后一个元素进行零初始化。 This is how aggregate initialization works and you can't change it. 这是聚合初始化的工作方式,您无法更改它。

What you need to do is either add overloads for arrays of size 1 and 2 and delete them, or you could just change the function to have 3 parameters and then it must be called with 3 values. 您需要做的是为大小为1和2的数组添加重载并删除它们,或者您可以只更改函数以包含3个参数,然后必须使用3个值调用它。

Here's one way to do it: 这是一种方法:

#include <array>
#include <iostream>

template<int N, typename ...Args>
void test(Args... args)
{
    static_assert(sizeof...(args) == N);
    std::array<int, N> arr{ args... };
    for (auto&& elm : arr) {
        std::cout << elm << '\n';
    }
}

int main()
{
    test<3>(1, 2, 3); // OK
    //test<3>(1, 2);    // Crashes

    //test<2>( 1, 2, 3 ); // Crashes
    test<2>(1, 2);    // OK

    return 0;
}

Uses variadic templates instead. 使用可变参数模板。

A bit ugly, but should work - a wrapper for std::array : 有点难看,但应该工作 - std::array的包装:

class MyArray 
{
public:
    MyArray(int x, int y, int z): _array{x, y, z} 
    {};
private:
    std::array<int, 3> _array;
};

void test(const MyArray&) {
    //no need to check values here
}

You won't be able to create an object of this wrapper class with less than 3 arguments. 您将无法使用少于3个参数创建此包装类的对象。 See it online . 在线查看

Of course, it won't work for general case you mentioned, but it should make it possible to differentiate certain classes. 当然,它不适用于您提到的一般情况,但它应该可以区分某些类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM