为什么析构函数不能是模板

Why destructor cannot be template?

本文关键字:不能 析构函数 为什么      更新时间:2023-10-16

我不想在类联合中使用SFINAE禁用用户声明的析构函数,就像在类中使用构造函数一样:

#include <type_traits>
#include <cstdlib>
template< typename A, typename B >
struct U
{
    constexpr U() = default;
    constexpr U(A _a) : a(_a), s{false} {}
    constexpr U(B _b) : b(_b), s{true}  {}
    union
    {
        A a;
        B b;
    };
    bool s;
    template< typename = std::enable_if_t< !(std::is_trivially_destructible< A >{} && std::is_trivially_destructible< B >{}) >, // disable if A and B is trivially destructible
              bool is_noexcept = (noexcept(std::declval< A >().~A()) && noexcept(std::declval< B >().~B())) > // disable if A or B is not destructible
    ~U() noexcept(is_noexcept)
    {
        if (s) {
            b.~B();
        } else {
            a.~A();
        }
    }  
};
int main()
{ 
    struct A {};
    struct B {};
    U< A, B > u;
    static_assert(std::is_literal_type< A >{});
    static_assert(std::is_literal_type< B >{}); // =>
    static_assert(std::is_literal_type< U< A, B > >{});
    return EXIT_SUCCESS;
}

但出现错误:

main.cpp:24:5: error: destructor cannot be declared as a template
    ~U() noexcept(is_noexcept)
    ^
1 error generated.
Failure!

C++中存在这种限制的理论原因吗?还是仅仅是"遗产"?

任何类U都可以有一个且只有一个析构函数,该析构函数在名为~U()的类中声明,不接受任何参数。

模板函数指定函数族;家庭;描述一个包含一个或多个成员的集合,对成员数没有上限。

这两个概念是相互排斥的。一个类不能同时只有一个析构函数和一系列析构函数。

作为解决方案,您可以添加层和专业化,比如:

template <typename A, typename B,
          bool trivially_destructible = std::is_trivially_destructible<A>{}
                                    && std::is_trivially_destructible<B>{},
          bool is_no_except = noexcept(std::declval<A>().~A())
                        && noexcept(std::declval<B>().~B())>
struct UdestructorImpl;
template <typename A, typename B, bool is_no_except>
struct UdestructorImpl<A, B, true, is_no_except>
{
    ~UdestructorImpl() noexcept(is_no_except) = default;
}
template <typename A, typename B, bool is_no_except>
struct UdestructorImpl<A, B, false, is_no_except>
{
    ~UdestructorImpl() noexcept(is_no_except) = delete;
}
template< typename A, typename B > struct U : UdestructorImpl<A, B>
{
    // Implementation
};