C++ 在std::数组上使用std::extent
我有一个模板化函数,我想C++ 在std::数组上使用std::extent,c++,arrays,templates,static-assert,C++,Arrays,Templates,Static Assert,我有一个模板化函数,我想static\u断言它的类型大小为3。此代码说明了我正在尝试执行的操作,但不起作用: template < typename T > void foo( T& param ) { // This line is the one that I need to figure out how to write static_assert( 3 == std::extent< T >::value, "param must have
static\u断言它的类型大小为3。此代码说明了我正在尝试执行的操作,但不起作用:
template < typename T >
void foo( T& param )
{
// This line is the one that I need to figure out how to write
static_assert( 3 == std::extent< T >::value, "param must have a size of 3" );
}
int main( void )
{
int cArray[3];
std::array< int, 3 > stdArray;
foo( cArray );
foo( stdArray );
}
模板
无效foo(T¶m)
{
//这一行是我需要弄清楚如何写的
static_assert(3==std::extent::value,“param的大小必须为3”);
}
内部主(空)
{
int cArray[3];
std::数组标准数组;
富(凯瑞);;
foo(stdArray);
}
我怀疑您有此错误,因为在编译时(即计算*static_assert*时),cArray和stdArray的维度未知,并且std::extent返回零:
事实上,如果将条件更改为零,则错误将消失:
静态断言(std::extent::value==0,“参数不是零”);
然而,正如在其他文章中已经指出的,std::extent不适用于std::array,只适用于诸如cArray之类的内置数组
OP编辑后:
既然您已经修改了foo以接受引用,那么cArray的std::extent报告将为3,stdArray的报告将为0(零)。因此,您将在编译时继续出现异常,因为stdArray的维度不是3。
std::extent
是为内置数组定义的。对于std::array
使用std::tuple\u size
。我不知道什么特质对两者都有效,但很容易写出一个:
template<typename T>
struct array_size : std::extent<T> { };
template<typename T, size_t N>
struct array_size<std::array<T,N> > : std::tuple_size<std::array<T,N> > { };
更喜欢通用引用
T&¶m
,否则只能使用左值。我想不出一种方法来编写一个同时处理这两个函数的函数,但重载就是为了这个
template <std::size_t N, typename T, std::size_t Bound>
void check_array_size( T (&)[Bound] )
{
static_assert(Bound == N, "incorrect array size");
}
template <std::size_t N, typename T, std::size_t Bound>
void check_array_size( const std::array<T,Bound>& )
{
static_assert(Bound == N, "incorrect array size");
}
template <std::size_t N>
void check_array_size( ... )
{
static_assert(N<0, "argument is not an array");
}
template <typename T>
void foo(T& param)
{
check_array_size<3>(param);
// actual function implementation...
}
模板
无效检查数组大小(T(&)[绑定])
{
静态_断言(绑定==N,“数组大小不正确”);
}
模板
无效检查数组大小(常量std::数组&)
{
静态_断言(绑定==N,“数组大小不正确”);
}
模板
无效检查数组大小(…)
{
静态断言(N这是基于的解决方案
template < typename T >
void foo( T& param )
{
static_assert( 3 == ( std::is_array< T >::value ? std::extent< T >::value : std::tuple_size< T >::value ), "param must have a size of 3" );
}
模板
无效foo(T¶m)
{
静态断言(3==(std::is_array::value?std::extent::value:std::tuple\u size::value),“参数的大小必须为3”);
}
尝试通过引用传递吗?我认为C数组不喜欢这样通过值传递。你应该解释它是如何“不工作”的。你有错误吗?哪些错误?我认为他/她得到的是“param的大小必须为3”在编译时。感谢Neil Kirk,我确实错过了那里的&
。DrD是正确的,静态断言触发。这是正确的,但即使如此,他仍然会继续为cArray产生相同的错误,这是一个内置错误array@DrD这是为什么?它的大小在编译时就知道了,对吗?@aschepper你说得对,在T¶m更改之后就不知道了。问题是T正如OP定义的那样,foo接收数组的副本。在任何情况下,尽管std不接受T&becuase std::array,但错误仍然存在:extent@DrD好的,对于这种类型规范化,您需要使用std::remove\u reference
后跟std::remove\u cv
。将它们嵌入到类型特征中不是一个好主意ode>foo(T参数)
将收到指向数组的第一个元素的指针,而不是数组的副本。OP已被编辑。在纠正了我自己的错误后,它似乎起了作用!非常优雅的解决方案,恭喜!很好。另一种选择是使用数组_size=std::integral\u constant::value?std::extent模板e_size::value>;
@iavr我在你的答案中也看到了使用关键字的。你能给我解释一下这是怎么回事吗?@JonathanMee-see(从C++11开始)。前者(在我的答案中)只是typedef
的一种替代语法。后者(如我之前的评论中)是typedef
(大致)什么是普通类的类模板。如果你使用类型,这非常方便。@iavr哇,好的,所以我可以使用static\u assert(3=array\u size,“param的大小必须为3”)
或者我甚至可以在std::enable_if
中使用它吗?我相信我对类型别名的理解已经足够好了,但我仍然在试图弄清楚std::integral_constant
和别名模板。无论如何,如果您想将其编辑到您的答案中,我很乐意接受。
template <std::size_t N, typename T, std::size_t Bound>
void check_array_size( T (&)[Bound] )
{
static_assert(Bound == N, "incorrect array size");
}
template <std::size_t N, typename T, std::size_t Bound>
void check_array_size( const std::array<T,Bound>& )
{
static_assert(Bound == N, "incorrect array size");
}
template <std::size_t N>
void check_array_size( ... )
{
static_assert(N<0, "argument is not an array");
}
template <typename T>
void foo(T& param)
{
check_array_size<3>(param);
// actual function implementation...
}
template < typename T >
void foo( T& param )
{
static_assert( 3 == ( std::is_array< T >::value ? std::extent< T >::value : std::tuple_size< T >::value ), "param must have a size of 3" );
}