简体   繁体   English

非类模板中数据成员 std::array 的编译时间大小 (C++14)

[英]Compile time size of data member std::array in non-class template (C++14)

Compile-time inspection std::array data member for its (compile time) size编译时检查 std::array 数据成员的(编译时)大小

I need to statically assert that the compile-time size of a non-constexpr data member of type std::array , say arr_ , of a non-template class is equal to a given (externally provided) constant.我需要静态断言非模板类的std::array类型的非 constexpr 数据成员的编译时大小,比如arr_ ,等于给定的(外部提供的)常量。 The static assertion will be done from inside the class, meaning arr_ is accessible, but I cannot rely on any stored constant (nor a non-type template parameter) for its size.静态断言将从类内部完成,这意味着arr_是可访问的,但我不能依赖任何存储的常量(也不是非类型模板参数)的大小。 Ie, the assertion needs to rely solely on "some inspection" of the arr_ data member.即,断言需要仅依赖于arr_数据成员的“一些检查”。

I would basically be done if the constexpr std::array<>::size() / std::array<>::max_size() was static member functions ( decltype(arr_)::size() / decltype(arr_)::max_size() ) instead of a non-static member functions.如果constexpr std::array<>::size() / std::array<>::max_size()是静态成员函数( decltype(arr_)::size() / decltype(arr_)::max_size()我基本上会完成decltype(arr_)::max_size() ) 而不是非静态成员函数。

I have a working approach using function template argument deduction on a pointer-to-data-member for the arr_ member, but I'm wondering if there is an easier/neater approach.我有一种在arr_成员的指向数据成员的指针上使用函数模板参数推导的工作方法,但我想知道是否有更简单/更整洁的方法。

#include <array>
#include <cstddef>

// Defined/provided from elsewhere.
constexpr std::size_t kArraySize = 12U;
constexpr std::size_t kAnotherArraySize = 12U;

template <typename T, typename U, std::size_t N>
constexpr std::size_t size_of_data_member_array(std::array<T, N> U::*) {
    return N;
}

class Foo {
    std::array<int, kArraySize> arr_;
    static_assert(size_of_data_member_array(&Foo::arr_) == kAnotherArraySize, "");
};

int main() {}

The standard provides a static version of array::size under the name tuple_size :该标准在名称tuple_size下提供了array::size的静态版本:

#include <array>
#include <tuple> // for std::tuple_size_v

static_assert(std::tuple_size<decltype(arr_)>::value == kAnotherArraySize, "");
static_assert(std::tuple_size_v<decltype(arr_)> == kAnotherArraySize); // C++17

You can create an instance of an array with the same type of Foo::arr_ within the static assertion:您可以在静态断言中创建一个具有相同类型Foo::arr_的数组实例:

class Foo {
    std::array<int, kArraySize> arr_;
    static_assert(decltype(arr_){}.size() == kAnotherArraySize, "");
};

See this example .请参阅此示例

Note : this works only if the array value type is a POD or has a default constexpr constructor.注意:这仅在数组值类型是 POD 或具有默认 constexpr 构造函数时才有效。

Just to offer another option, you can do partial specialization on template variables.只是为了提供另一种选择,您可以对模板变量进行部分专业化。

#include <array>
#include <cstddef>

// Defined/provided from elsewhere.
constexpr std::size_t kArraySize = 12U;
constexpr std::size_t kAnotherArraySize = 12U;

template <typename T>
constexpr std::size_t array_size = 0;

template <typename T, std::size_t N>
constexpr std::size_t array_size<std::array<T, N>> = N;

class Foo {
    std::array<int, kArraySize> arr_;
    static_assert(array_size<decltype(arr_)> == kAnotherArraySize, "");
};

int main() {}

To offer yet another option using SFINAE:使用 SFINAE 提供另一种选择:

#include <type_traits>
#include <array>

template <typename T>
constexpr bool is_array_v = false;

template <typename T, size_t N>
constexpr bool is_array_v<std::array<T, N>> = true;

template <typename Array, std::enable_if_t<is_array_v<Array>, int> = 0>
constexpr size_t array_size_v = std::tuple_size<Array>::value;

static_assert(array_size_v<std::array<int, 5>> == 5); // OK
static_assert(array_size_v<int> == 5);                // Won't compile

Unlike the other proposals, this will catch misuse of array_size_v at compile time, so entering an int and other types which are not std::array won't work.与其他提议不同,这将在编译时发现对array_size_v误用,因此输入int和其他不是std::array类型将不起作用。

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

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