【发布时间】:2016-02-25 09:08:40
【问题描述】:
我不想在类联合类中使用 SFINAE 禁用用户声明的 destructor,就像在类中的 constructors 一样:
#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++ 中这种限制有理论上的原因吗?还是只是“遗产”?
【问题讨论】:
-
@DavidHaim 默认构造函数也无法获取参数,但可以是模板。
-
必须生成析构函数,默认构造函数不需要(类可能有其他构造函数)。
-
请看我的回答
-
还没有人提到:如果因为某个对象超出范围而自动调用析构函数,应该使用什么模板类型? ... 正确的。同理解释了为什么不能有正常的函数参数。
-
@deviantfan 整个(包括虚构的析构函数选择)类模板在构造点实例化。范围无关紧要。
标签: c++ templates destructor sfinae