Com*_*sMS 11 c++ type-traits language-lawyer c++11
std::is_constructible
具有私有或受保护的析构函数的类型的预期结果是什么?
例如,我仍然可以在堆上构造这样的对象,即使只有朋友可以释放它:
#include <type_traits>
class Foo
{
friend void freeFoo(Foo*);
public:
Foo()
{}
private:
// Destructor is private!
~Foo()
{}
};
void freeFoo(Foo* f)
{
delete f; // deleting a foo is fine here because of friendship
}
int main()
{
Foo* f = new Foo();
// delete f; // won't compile: ~Foo is private
freeFoo(f); // fine because of friendship
if(!std::is_constructible<Foo>::value)
{
std::cout << "is_constructible failed" << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
is_constructible
对gcc和Visual C++(coliru上的gcc演示)进行最终检查都会失败.
这是标准所要求的行为吗?如果是这样,有没有办法检查类型是否具有特定的构造函数,无论析构函数上的访问说明符是什么?
Col*_*mbo 13
C++ 14 FD定义is_constructible
如下:
给出以下函数声明:
Run Code Online (Sandbox Code Playgroud)template <class T> add_rvalue_reference_t<T> create() noexcept;
is_constructible<T, Args...>
当且仅当以下变量定义适用于某些发明变量时,才应满足模板特化的谓词条件t
:Run Code Online (Sandbox Code Playgroud)T t(create<Args>()...);
执行访问检查就好像在与其无关的上下文
T
中执行Args
.仅考虑变量初始化的直接上下文的有效性.[ 注意:初始化的评估可能会导致副作用,例如类模板特化和函数模板特化的实例化,隐式定义函数的生成等等.这种副作用不在"直接背景"中,并且可能导致程序形成不良.- 尾注 ]
现在问题基本上简化为"析构函数是否在变量初始化的直接上下文中调用?" [class.dtor]/11:
隐式调用析构函数
- 对于在程序终止时具有静态存储持续时间(3.7.1)的构造对象(3.6.3),
- 对于具有自动存储持续时间(3.7.3)的构造对象,当创建对象的块退出时(6.7),
- 当一个构造的临时对象的生命周期结束时(12.2).
在每种情况下,调用的上下文都是对象构造的上下文.
因此,析构函数调用是在构造的上下文中(这可能与此处的初始化同义),这意味着它被考虑并导致特征返回false
.
我认为这是不明确的(例如,即时与非明确的直接上下文?),但直观地说,我希望符合标准的实现将表达标记NotDestructible()
为格式错误 - 无论是SFINAE还是不友好(最好是前者).但是,从来没有良好的形式.
用libc ++,libstdc ++和GCC来表示它是无效的,SFINAE友好.
如果是这样,有没有办法检查类型是否具有特定的构造函数,无论析构函数上的访问说明符是什么?
怎么用new
?
template <typename T, typename... Args>
class is_only_constructible
{
template <typename, typename=void> struct test : std::false_type {};
template <typename U>
struct test<U, decltype(void(new U(std::declval<Args>()...)))> : std::true_type {};
public:
static constexpr bool value = test<T>::value;
};
Run Code Online (Sandbox Code Playgroud)
演示.可以很容易地建立一致的特征:获取is_only_constructible
特征并将其与之结合is_destructible
(显然,后者false
在与私有析构函数结合时返回).
引用C++标准(草案N4296)的段落[meta.unary.prop]/7:
给出以下函数声明:
Run Code Online (Sandbox Code Playgroud)template <class T> add_rvalue_reference_t<T> create() noexcept;
is_constructible<T, Args...>
当且仅当以下变量定义适用于某些发明变量时,才应满足模板特化的谓词条件t
:Run Code Online (Sandbox Code Playgroud)T t(create<Args>()...);
换句话说,如果析构函数不可访问,则为is_constructible<T, Args...>::value
yield false
.
归档时间: |
|
查看次数: |
666 次 |
最近记录: |