获取数组指针模板参数的大小
Get size of an array-pointer template parameter
我想知道是否可以自动推断数组的大小,该数组作为模板参数传递,而不(显式(传递其大小。
以下代码在g++4.8和clang++3.3(使用-std=c++11 -Wall
(上都编译了warning-less。
#include <iostream>
template<const int* arr>
struct array_container
{
static constexpr int val = arr[1];
array_container() {
std::cout << val << std::endl;
}
// static constexpr int arr_size = ??;
};
constexpr int one[] = { 1 };
constexpr int two[] = { 1, 2 };
int main()
{
// array_container<one> array_one;
array_container<two> array_two;
// (void) array_one;
(void) array_two;
return 0;
}
但是,如果我删除main()
中的两个注释符号,那么两个编译器都会出现越界错误。
现在,这很酷。尽管const int* arr
的类型是指针,但编译器不知何故知道数组的大小。有没有办法得到arr的大小,例如在array_container
中完成我的评论?
当然,你不允许进入
- 使用任何宏
- 将大小存储在arr中(例如,传递std::数组作为模板参数:
constexpr std::array<int, 1> one = { 1 }
,或在字符串中使用类似' '
的结束标记( - 对于不能自动推导(
array_container<1, one> array_one
(的大小,请使用额外的模板参数
也许C++11标准库<type_traits>
头中的std::extent
模板就是您想要的:
#include <iostream>
#include <type_traits>
constexpr int one[] = { 1 };
constexpr int two[] = { 1, 2 };
int main()
{
std::cout << std::extent<decltype(one)>::value << std::endl;
std::cout << std::extent<decltype(two)>::value << std::endl;
return 0;
}
输出:
1
2
template<size_t size>
constexpr size_t arraySize ( const int ( &arrayRef ) [size] ) {
return size;
}
int main(){
int A[1];
int B[2];
cout << arraySize(A) << arraySize(B);
return 0;
}
我相信像这样的东西就是你想要的,使用数组引用。声明数组引用的语法看起来有点像函数指针的语法。此函数模板接受一个名为arrayRef的数组引用,它可以防止数组到指针的衰减,从而保留有关数组大小的编译时信息。正如您所看到的,模板参数对于编译器是隐式的。请注意,只有在编译时可以推导出大小时,这才能起作用。有趣的是,在不命名arrayRef的情况下,这应该仍然有效。为了使上述模板更加有用,您还可以添加一个模板参数来推断数组的类型。为了清楚起见,我省略了它。
可能不会,因为SFINAE只发生在即时上下文中,而该错误来自于constexpr
中的UB导致编译时错误的要求,我认为这不是即时的。你可以尝试一个在UB上停止的递归SFINAE,但即使它有效,你也必须检查标准,并希望它不会改变(因为它相当模糊和新(。
简单的方法是ise函数来推导数组大小,必须显式地将其传递给类型,然后将其存储在auto
中。可能不是你想要的。
有人建议允许从值参数中推导类型参数,因此您可以等待这些参数。
不是一个可靠的答案,更多的是一个扩展的评论,所以标记为社区维基。
这确实是可能的。我用SFINAE找到了一个解决方案。如果索引超出范围(本例中的第3行(,它基本上会产生替换错误:
template<class C>
static yes& sfinae(typename val_to_type<
decltype(*C::cont::data), *(C::cont::data + C::pos)>::type );
template<class C>
static no& sfinae(C );
完整的源代码在github上。
只有两个缺点:
- 您必须指定数组的类型(这是不可避免的(
- 它只适用于g++4.8.1和clang 3.3。g++对于空字符串失败(带有编译器错误(。如果有人能为其他编译器进行测试,我们将不胜感激
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 如何使用Visual Studio 2017在C++中为参数化对象数组使用唯一指针
- 为 NewObjectA() 函数创建 jvalues 的参数数组时出错 - JNI Invocation API
- 估计函数参数数组的维度
- 温度参数数组的内存泄漏
- 如何将值附加到命令行参数数组?
- libpqxx:如何绑定参数数组
- 如何在德尔福中C++参数数组指针算术
- C++函数参数或参数数组
- 将 std::function 代理为需要参数数组的 C 函数
- 分析字符串参数数组
- Pro*C传递参数数组
- OpenCV错误:cvGetSize中的错误参数(数组应该是CvMat或IplImage)
- c++无限参数数组
- 查找命令行参数数组中的元素数
- 如何将目录中所有具有完整路径的文件传递到execv中的参数数组
- ODBC:参数数组-忽略参数
- 使用lambda参数数组