部分模板专用化数组使用情况
Partial template specialization array usage
我一直在尝试区分传递给构造函数的参数是数组还是简单指针的情况。所以,我写了这个示例代码
#include <iostream>
#include <type_traits>
using std::cout;
using std::endl;
// here I create a structure which I intend to use
// to tell arrays from non-arrays.
template<typename T>
struct TypeTraits {
static bool const IsArray = false;
};
template<typename T>
struct TypeTraits<T[]> {
static bool const IsArray = true;
};
// And here I create a container to store a pointer.
template<typename TValue>
class Ptr_container {
TValue * ptr;
public:
template<typename T>
explicit Ptr_container(T from_ptr) :
ptr (from_ptr)
{
cout << std::boolalpha;
cout << TypeTraits<T>::IsArray << endl;
cout << "Just to be sure: " << std::is_array<T>::value << endl;
}
~Ptr_container()
{
delete ptr;
}
};
int main () {
Ptr_container<int> a (new int(2));
Ptr_container<int> b (new int[2]);
return 0;
}
结果是false。所以,我显然做错了什么,问题是,当使用new T和new T[N]分配新内存时,我应该怎么区分情况?
更新:我使用std::is_array
添加了一个"arrayness"检查,但它不会改变结果。在编译时必须有某种方法来检测"数组性",因为以下原因:boost::shared_ptr
将指针作为构造函数的参数,并且其内部结构仅使用该信息进行初始化。在boost::shared_ptr
类的某个地方,有一个结构决定如何删除shared_ptr
(使用delete
或delete[]
)指向的内存。
实际上,我正在尝试实现shared_ptr
的某些部分,但在阵列识别阶段失败了。
更新2我终于弄明白了,所以我结束了这个问题。该问题的解决方案是向模板中添加另一个参数,并以类似的方式初始化容器
Ptr_container<int, PointerProperty> pa (new int(4));
Ptr_container<int, ArrayProperty> pv (new int[4]);
您绝对无法区分编译时从new
和new[]
返回的指针。不使用模板,或带有编译器挂钩的标准类型特征,也不使用任何其他技术。
这样做的原因应该是显而易见的;如果不是,请考虑以下代码:(事情不是这样工作的;我只是以你的例子为例。)
int * p = nullptr;
if (rand() % 2 == 0)
p = new int;
else
p = new int [42];
print_is_array (p); // Assume this does the detection and prints something.
您(和编译器)如何在编译时知道p
将使用new
还是new[]
分配?
此外,您所称的"数组"更恰当地称为"vector"(不要与std::vector
混淆。)数组具有一些编译时属性(如大小),而运行时分配的内存块则没有,即使您碰巧在其中构造了多个对象(例如,使用new[]
)。
并且,将一个T
s的数组(一个真实的、适当的编译时数组)传递到一个接受T *
s的函数中,将"衰减"类型并失去"arrayness"。我在这里指的是您定义构造函数的方式,即它采用T *
。
如果您想了解如何在编译时检测(正确的)数组,请查看<type_traits>
标头中std::is_array<T>
模板的实现。
编辑:顺便说一句,这就是我说的(正确的)数组的意思:
int a [42];
不是这个:
int * p = new int [42];
这是两种不同的类型,但第一种类型可以"衰减"并隐式转换为第二种类型。
正如Zeta在评论中所说:
typeof (new int) == typeof (new int[]) == int *
但是,如果您需要区分使用new
和new[]
创建的类的对象,则重载这些运算符将更有意义。
- 从父数组测试用例构造二叉树失败
- 为什么用结构初始化数组需要指定结构名称
- 为什么不能用常量表达式声明数组?
- 我们可以用参数化构造函数初始化结构的数组吗?
- 用数据填充未指定大小的数组
- 创建整数的 2D 数组,该数组将使用两个函数用随机数填充矩阵.我做错了什么?
- 用空格填充 2D 数组(从文件输入)
- 为什么数组的 GCC 聚合初始化首先用零填充整个事物,包括非零元素?
- 在创建动态二维数组时,在A[i*c+j]中使用c有什么用,即c代表什么
- 用c++排序,不带数组
- 用数组在sfml中定义圆形
- c++用输入数据创建数组
- 用现代C++STL数据结构替换旧的C风格数组
- 如何将 numpy 二维数组作为一种可以用C++读取的二进制格式存储在磁盘上
- 用于查找连续子数组的最大总和的代码使测试用例失败
- 我正在编写一个代码来将 int 数组存储在文件中,然后用 c++ 检索它,但是检索第一项是假值,我该如何解决这个问题?
- 用数组或指针引用函数?
- 用 int 值填充 char 数组
- C 中的动态数组(用指针表示) - 输入元素
- 2D 矢量数组用零而不是双精度值填充