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

问题描述

编译时检查std :: array数据成员的(编译时)大小

我需要静态断言, non-template 类的类型为std::array的类型arr_的非constexpr数据成员的编译时大小为等于给定(外部提供)的常数。静态断言将从类内部完成,这意味着arr_是可访问的,但是我不能依靠任何存储的常量(也不依赖于非类型模板参数)来确定其大小。也就是说,断言只需要依靠arr_数据成员的“某些检查”即可。

如果constexpr std::array<>::size() / std::array<>::max_size()是静态成员函数(decltype(arr_)::size() / decltype(arr_)::max_size())而不是非静态成员,则基本上可以完成功能。

我有一种有效的方法,在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() {}

解决方法

该标准在名称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
,

您可以在静态断言中创建具有相同类型Foo::arr_的数组实例:

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

请参见this example

注意:仅当数组值类型为POD或具有默认的constexpr构造函数时,此方法才有效。

,

仅提供另一种选择,您可以对模板变量进行部分专业化。

#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() {}
,

使用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

与其他建议不同,这将在编译时捕获array_size_v的滥用,因此输入int和其他非std::array的类型将无效。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...