我正在查看std::unique_ptr
std::unique_ptr<T[]>
并注意到C ++ 17似乎已经做了一些有趣的改动。特别是,std::unique_ptr::pointer
的特化现在接受模板参数,它之前只接受reset
个参数。例如,以下是std::unique_ptr<T[]>
的一个template <typename U> void reset(U p);
成员函数的声明:
reset
该网站声明:
与主模板的
U
成员的行为相同,只是它只参与重载解析pointer
与pointer
的类型相同,或者element_type*
与U
的类型相同,而V*
是指针类型V(*)[]
,因此element_type(*)[]
可转换为delete[]
。
我假设这是为了安全 - 你不想对指向指向其基类型指针的派生类型数组的指针执行#include <type_traits>
struct foo {};
struct bar : public foo {};
static_assert(!std::is_convertible_v<bar(*)[], foo(*)[]>);
(在C +之前) +17这被标记为已删除)。正如所料,这段代码编译得很好:
static_assert
然而,有趣的是,以下不编译,两个#include <type_traits>
struct foo {};
struct bar : public foo {};
static_assert(std::is_convertible_v<bar*(*)[], foo*(*)[]>);
static_assert(std::is_convertible_v<std::unique_ptr<bar>(*)[], std::unique_ptr<foo>(*)[]>);
都失败了:
$scope.onSelect = function(item) {
// you existing code...
if($scope.newData.category === "Add new category") {
$scope.newData.category = ''; // set to empty string so the input box is empty
$scope.showAddCategory = true;
}
}
为什么?在什么情况下会使用这种重载?
答案 0 :(得分:5)
这基本上是一种说法“如果可以安全地传递一个较少的常量指针”,例如,int* p = /*...*/; unique_ptr<const int []> up; up.reset(p);
对于不同类型U
和V
,U(*)[]
(隐式)可转换为V(*)[]
的唯一情况是qualification conversion,即您要在类型中的正确位置添加const
/ volatile
。确切的规则很复杂(因为它们处理任意嵌套的指针/指向成员/数组的指针;如果你想知道的话,点击链接),但它们基本上只允许在安全时进行转换; unique_ptr
的规范然后利用这个事实,这样它就不必重新定义“安全”,代价是使意图变得更加神秘。
答案 1 :(得分:0)
struct foo {};
struct bar : public foo {};
在这个简单的案例中,foo*
的值表示很可能与bar*
的值表示完全相同,因此可以可以在它们的数组之间进行转换。但是,只要bar
变得更复杂,它就不再成立。考虑一下:
struct foo {};
struct qux {};
struct bar : qux, foo {};
现在,bar*
可隐式转换为foo*
,但该转化不会保留其准确值:它需要从qux
到foo
的偏移。< / p>
同样,只要虚拟,多个访问控制级别等进入图片,基类子对象的地址就会变得与最派生对象的地址不同。这样的指针甚至可以具有不同的大小(1)。
这就是为什么只有一组有限的案例,derived*
可以用作base*
而没有改变价值的转化。我的猜测是,对有限的情况进行补贴会使标准变得复杂,效果不大,因此不允许在这些指针数组之间进行转换。
(1)这有点模糊,但如果C ++编译器受到设计不佳的C ABI的限制,可能会发生这种情况。 This answer讨论了这种情况。