C++ 部分模板专用化数组用法

C++ 部分模板专用化数组用法,c++,template-specialization,C++,Template Specialization,我一直在尝试区分传递给构造函数的参数是数组还是简单指针的情况。因此,我编写了这个示例代码 #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>

我一直在尝试区分传递给构造函数的参数是数组还是简单指针的情况。因此,我编写了这个示例代码

#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;
}

正如齐塔人在评论中所说:

typeof (new int) == typeof (new int[]) == int *

但是,如果您需要区分使用
new
new[]
创建的类的对象,重载这些操作符将更有意义。

您绝对无法区分编译时从
new
new[]
返回的指针。不使用模板,或编译器挂钩的标准类型特征,也不使用任何其他技术

原因应该是显而易见的;如果不是,考虑下面的代码:(事情不是这样工作的,我只是跟随你的例子。)< /P> 您(和编译器)如何在编译时知道是否将使用
new
new[]
分配
p

此外,您所称的“数组”更确切地称为“向量”(不要与
std::vector
)数组具有一些编译时属性(如大小),即使您碰巧在其中构造了多个对象(例如,使用
new[]
),运行时分配的内存块也没有这些属性

并且,将
T
s数组(一个真实的、适当的编译时数组)传递给接受
T*
s的函数将“衰减”类型并丢失“数组”。这里我指的是您定义构造函数的方式,即它采用
T*

如果您想了解如何在编译时检测(正确的)数组,请查看
标题中
std::is_array
模板的实现

编辑:顺便说一下,这就是我说的(正确的)数组的意思:

不是这个:

int * p = new int [42];

这是两种不同的类型,但第一种类型可以“衰减”并隐式转换为第二种类型。

new
new[]
返回指针。该指针只包含新分配内存的地址,没有大小信息等等,所以
typeof(newint)==typeof(newint[])==int*
。但是,我相信您正在尝试实现
std::unique_ptr
std::vector
已经提供的功能。伙计,
std::is_array
。@KerrekSB如果new[]返回T*(它很快就会返回),那么std::is_array::value将始终为false,不是吗?他实际上需要传入int[]这样的值才能返回真值。@ScarletAmaranth:是的,我只是指OP代码中正在进行的轮子改造。
boost::shared\u ptr
只有将信息放入数组类型中,才能安全地保存数组(
boost::shared_ptr
,从v1.53开始),或者如果您提供了一个自定义的删除程序。类似地
std::unique_ptr
,但是没有std等价物
std::shared_ptr
。您要说的是
new
new[]
返回
T*
)。当然是这样。我认为OP可能需要一些基本原理来配合它(无论它的表现和解释多么糟糕!):我只是认为在开始考虑运行时之前先静态思考总是一个好主意。new和new[]都返回T*,它们之间没有隐藏的区别,都在签名中,因此您无法真正区分。不过,你的insta nullptr触感很好!:)是的,这似乎回答了为什么我的代码不能按我的预期工作。然而,我的问题还有第二部分:如何实施这种承认?不过,谢谢你的提示。
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.
int a [42];
int * p = new int [42];