围绕静态断言不完整的类型
Work around incomplete type in static assert
当表达式取决于类类型本身时,是否有一种方法可以在类中static_assert?也许将评估延迟到模板实例化完成或之后的类型?
示例代码:
#include <type_traits>
template<typename T>
struct Test {
T x = 0; // make non-trivial
static_assert(std::is_trivial<Test<T>>::value, "");
};
int main() {
// would like static assert failure, instead get 'incomplete type' error
Test<int> test1;
Test<float> test2;
return 0;
}
这是一种使用助手类和间接类型的解决方案。我相信这没有缺点。
template<typename T>
struct TestImpl {
T x = 0; // make non-trivial
};
template<typename T>
struct TestHelper {
using type = TestImpl<T>;
static_assert(std::is_trivial<type>::value, "");
};
template<typename T>
using Test = typename TestHelper<T>::type;
编辑:可以将testHelper移至testimpl:
template<typename T>
struct TestImpl {
T x = 0; // make non-trivial
struct Helper {
using type = TestImpl;
static_assert(std::is_trivial<type>::value, "");
};
};
template<typename T>
using Test = typename TestImpl<T>::Helper::type;
我也在寻找使用static_assert的解决方案,但约束也有效:
#include <type_traits>
namespace Private {
template<typename T>
struct Test {
T x = 0;
};
}
template<typename T>
requires std::is_trivial<Private::Test<T>>::value
using Test = Private::Test<T>;
int main() {
Test<int> test1;
Test<float> test2;
return 0;
}
您可以定义击曲线并将static_assert放在那里,至少使用G 5.4 -STD = C 11这可以使用。
(从评论移动)
您可以添加一个中间类以保持逻辑,并让您的客户实例化派生的类别,该类别仅包含static_assert
S
#include <type_traits>
template<typename T>
struct TestImpl {
T x = 0; // make non-trivial
};
template<typename T>
struct Test : TestImpl<T> {
static_assert(std::is_trivial<TestImpl<T>>::value, "");
using TestImpl<T>::TestImpl; // inherit constructors
};
我不知道这是否完全合规,但GCC中继和clang trunk都接受了:
#include <type_traits>
template<typename T>
constexpr bool check_trivial()
{
static_assert(std::is_trivial_v<T>);
return std::is_trivial_v<T>;
}
template<typename T>
struct Test
{
Test() noexcept(check_trivial<Test<T>>()) = default;
T x;
};
struct nontrivial
{
nontrivial(){}
};
int main() {
// would like static assert failure, instead get 'incomplete type' error
Test<int> test1;
Test<nontrivial> test2;
return 0;
}
使用DTOR而不是CTOR时它不起作用。YMMV。
这使您的类型成为非聚集。
如果您的类型具有任何强制性成员功能,则可以将static_assert
放在其中一个功能主体中。在类定义结束后对成员函数体进行评估,因此看不到不完整的类型。
对于模板,问题是并非所有成员函数始终是实例化的。在非实验性成员函数中的static_assert
不会发射。您需要在代码中某个地方的某个地方进行呼叫(实际使用任何ODR使用)才能强制实例化。
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 私有类型的静态常量成员
- C++ 模板类型的静态 lambda 成员的构造
- 给定一个C++嵌套的私有结构类型,是否有从文件范围静态函数访问它的策略
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 如何在没有实例的情况下获取非静态方法的类型?
- 值和类型的简洁双向静态 1:1 映射
- 静态自动 constexpr t = { "red" , "black" , "green" } 是什么类型;派生到?
- 非类类型表达式的静态类型与动态类型之间的差异
- 如何使用类型级函数动态创建静态类型?
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 指向 POD 类型的指针之间的静态转换与重新解释转换
- 为什么 std::bind 静态类型检查传递给函数的参数?
- 将 static_cast<int>(-15) 分配给静态常量字符类型变量
- 静态私有函数,模板化类型作为C++中的默认参数
- 从相同类型的静态成员进行类内初始化
- 在类定义中推导内联静态成员函数的返回类型
- 参考类型静态数据成员的问题可能是编译器错误
- 如何使用泛型在 C# 中将类型静态绑定在一起(如在 TypeToType <T>中)?
- double类型静态类成员的常量表达式初始化项