std :: is_constructible在具有非公共析构函数的类型上 [英] std::is_constructible on type with non-public destructor

查看:132
本文介绍了std :: is_constructible在具有非公共析构函数的类型上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在具有私有或受保护的析构函数的类型上, std::is_constructible 的预期结果是什么?

What is the expected result for std::is_constructible on a type with a private or protected destructor?

例如,即使只有一个朋友可以释放它,我仍然可以在堆上构造这样的对象:

For instance, I can still construct such an object on the heap even though only a friend can free it:

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

在gcc和Visual C ++上,对is_constructible的最终检查都将失败( coliru上的gcc演示)

The final check for is_constructible will fail on both gcc and Visual C++ (gcc demo on coliru).

这是标准所要求的行为吗?如果是这样,有没有办法检查类型是否具有特定的构造函数,而不管析构函数上的访问说明符如何?

Is that the required behavior by the standard? If so, is there any way to check whether the type has a specific constructor, regardless of the access specifier on the destructor?

推荐答案

C ++ 14 FD定义is_constructible如下:

The C++14 FD defines is_constructible as follows:

给出以下函数声明:

Given the following function declaration:

template <class T>
add_rvalue_reference_t<T> create() noexcept;

模板专业化的谓词条件 is_constructible<T, Args...>仅当且仅当满足 下面的变量定义对于某些发明是正确的 变量t:

the predicate condition for a template specialization is_constructible<T, Args...> shall be satisfied if and only if the following variable definition would be well-formed for some invented variable t:

T t(create<Args>()...);

执行访问检查就像在与T无关的上下文中一样 以及任何Args.仅在即时上下文中有效 [ Note :评估 初始化会导致副作用,例如 类模板专业化和功能模板的实例化 专业化,隐式定义函数的生成,以及 很快.此类副作用不在即时范围内",并且可以 导致程序格式错误. -尾注]

Access checking is performed as if in a context unrelated to T and any of the Args. Only the validity of the immediate context of the variable initialization is considered. [ Note: The evaluation of the initialization can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. —end note ]

现在,问题基本上简化为在变量初始化的直接上下文中进行析构函数调用吗?" [class.dtor]/11:

Now the question essentially reduces to "Is the destructor call in the immediate context of the variable initialization?" [class.dtor]/11:

析构函数被隐式调用

A destructor is invoked implicitly

  • 对于在程序终止(3.6.3)时具有静态存储持续时间(3.7.1)的构造对象,
  • 对于在创建对象的块退出(6.7)时具有自动存储持续时间(3.7.3)的已构造对象,
  • 对于构造的临时对象,当其生命周期结束时(12.2).
  • for a constructed object with static storage duration (3.7.1) at program termination (3.6.3),
  • for a constructed object with automatic storage duration (3.7.3) when the block in which an object is created exits (6.7),
  • for a constructed temporary object when its lifetime ends (12.2).

在每种情况下,调用的上下文都是 对象的构造.

In each case, the context of the invocation is the context of the construction of the object.

因此,析构函数的调用是在构造的上下文中进行的(在这里大概与初始化是同义的),这意味着将其考虑在内并导致特征返回false.
我认为这是未指定的(例如,即时还是非即时)?但是,从直觉上讲,我希望采用一致的实现将表达式NotDestructible()标记为格式错误-对SFINAE友好或不友好​​(最好是前者).不过,格式从不正确.
使用libc ++,libstdc ++和GCC编写的Clang确实说这是无效的,对SFINAE友好... >


Thus the destructor invocation is in the context of the construction (which is presumably synonymous to initialization here), which implies that it is considered and causes the trait to return false.
I believe this to be underspecified (e.g. immediate vs not-explicitly-immediate context?), but intuitively I expect a conforming implementation to mark the expression NotDestructible() as ill-formed - either SFINAE-friendly or not (preferably the former). Never well-formed, though.
Clang with libc++, libstdc++ and GCC do say that it's invalid, SFINAE-friendly.

如果是,是否有任何方法可以检查类型是否具有特定的 构造函数,而不管析构函数上的访问说明符是什么?

If so, is there any way to check whether the type has a specific constructor, regardless of the access specifier on the destructor?

使用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;
};

演示 .可以轻松建立一致的特征:将is_only_constructible特征与is_destructible结合使用(显然,当与私有析构函数结合使用时,后者会返回false).

Demo. Consistent traits can be easily established: Take the is_only_constructible trait and combine it with is_destructible (clearly the latter returns false when combined with private destructors).

这篇关于std :: is_constructible在具有非公共析构函数的类型上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆