sfinae 远离一个破坏者 [英] sfinae away a destructor

查看:49
本文介绍了sfinae 远离一个破坏者的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现与 std::vector 非常相似的东西,但在堆栈上使用数组而不是内存分配.

I am implementing something very similar to std::vector but uses array on the stack instead of memory allocation.

d-tor 调用使用 SFINAE 的函数.

The d-tor calls a function that uses SFINAE.

  • 如果 value_type 是 POD,则函数体为空.
  • 如果value_typestd::string这样的普通类,则该函数有一个主体并正确销毁所有数据.
  • If value_type is POD the function have empty body.
  • If value_type is normal class such std::string, the function have a body and destroy all the data properly.

现在,我希望能够使用这个新的 std::vector 作为 constexpr.然而,即使 c-tor 声明为 constexpr,代码也无法编译,因为该类具有非平凡的 d-tor.

Now, I want to be able to use this new std::vector as constexpr. However even the c-tor is declared constexpr, the code does not compiles because the class have non trivial d-tor.

这是代码的一小部分:

template<typename T, std::size_t SIZE>
class SmallVector{
    constexpr SmallVector() = default;

    ~SmallVector(){
        destructAll_<value_type>();
    }

    // ...

    template<typename X>
    typename std::enable_if<std::is_trivially_destructible<X>::value == true>::type
    destructAll_() noexcept{
    }

};

如果 value_type 是 POD 并保留非 POD 数据类型的功能,我可以做些什么来使类成为 constexpr.
(当然不是同时)

Is there anything I can do to make class be constexpr if value_type is POD and keeping functionality for non POD data types.
(Not at the same time of course)

推荐答案

until C+20

不幸的是,无法使用 SFINAE 启用/禁用析构函数,也无法使用未来的概念.那是因为析构函数:

  • 无法模板化
  • 不能有参数
  • 不能有返回类型

您可以做的是专门化整个类,或者更好的是,创建一个只包含构造/销毁和基本访问的基类,然后专门化它.

What you can do is specialize whole class, or better yet, create a base class that contains only the construct/destruct and basic access and specialize that.

template <class T, class Enable = void>
struct X {
    ~X() {}
};

template <class T>
struct X<T, std::enable_if_t<std::is_pod<T>::value>> {
};

static_assert(std::is_trivially_destructible<X<int>>::value);
static_assert(!std::is_trivially_destructible<X<std::vector<int>>>::value);

C++ 20

据我所知,您可以约束析构函数并以非常简单和优雅的解决方案获得您想要的内容:

C++ 20

As far as I can tell you can constraint a destructor and get exactly what you want in a very simple and elegant solution:

template<typename T, std::size_t SIZE>
class SmallVector{
public:
    constexpr SmallVector() = default;

    ~SmallVector() requires std::is_trivially_destructible_v<T> = default;

    ~SmallVector()
    {   
    }
};

static_assert(std::is_trivially_destructible_v<SmallVector<int, 4>>);
static_assert(!std::is_trivially_destructible_v<SmallVector<std::string, 4>>);

然而,这是一个全新的功能,最近发生了一些变化(例如,参见 禁用带有概念的非模板化方法),编译器支持仍然很粗略.gcc 编译得很好,而 clang 对析构函数有两个定义的事实感到困惑 godbolt

However this is a brand new feature and there have been some changes lately (e.g. see Disable non-templated methods with concepts) and the compiler support is still sketchy. gcc compiles this just fine, while clang is confused by the fact that there are two definitions of the destructor godbolt

这篇关于sfinae 远离一个破坏者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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