static_assert在模板或类中,gotcha
static_assert inside template or class, gotcha
在这个主题上,我读了很少的相关性,所以问题/答案/评论。在这里只发现了一个相关但有些掩埋的问题/答案。请允许我尝试以有关/答案方式清楚地显示问题。为了他人的利益。
让代码说话。想象一下您设计此模板。
// value holder V1.0
// T must not be reference or array or both
template<typename T> struct no_arrf_naive
{
static_assert(!std::is_reference_v<T>, "nnNo references!nn");
static_assert(!std::is_array_v<T>, "nnNo arrays!nn");
using value_type = T;
T value;
};
简单安全,可能会想。一段时间后,其他人将这个复杂的大型API埋葬在深处,然后开始使用它。上面的结构在内部深处。通常,他们只是使用它,而无需查看后面的代码。
using arf = int(&)[3];
using naivete = no_arrf_naive<arf>;
// the "test" works
constexpr bool is_ok_type = std::is_class_v< naivete >;
// this declaration will also "work"
void important ( naivete ) ;
但是。实例不起作用
naivete no_compile;
静态断言消息确实突然显示了。但是,"测试"如何编译和通过?这里发生了什么?
问题是API是错误的。static_assert作为班级成员进行"踢入",但在实例化之前不做。
首先,有害的API评论
template<typename T>
struct no_arrf_naive
{
// member declarations
// used only on implicit instantiation
// https://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation
static_assert(!std::is_reference_v<T>, "nnNo references!nn");
static_assert(!std::is_array_v<T>, "nnNo arrays!nn");
using value_type = T;
T value;
};
用户在这里正确编码以从模板转换为类型,但是static_assert的do not oke not oke of-not-not oken:
using naivete = no_arrf_naive<arf>;
这可能最令人担忧的是,直到有人想使用它。这不会编译,并且消息是API作者放置在那里的消息,最终将显示。但是las,为时已晚。
以及在一些大型C 来源上工作的项目,出现的问题是最臭名昭著的问题。
解决方案是良好的旧sfinae。API修复是这样的:
// value holder
// references or arrays or both are excluded at compile time
template<typename T,
std::enable_if_t<
(!std::is_reference_v<T> && !std::is_array_v<T>), bool> = true
> struct no_arrf
{
using value_type = T;
T value;
};
尝试使用引用或数组或两者从模板创建类型时,不会立即编译:
// reference to array of three int's
using arf = int(&)[3] ;
// no can do
using no_naivete = no_arrf<arf>;
(MSVC) error C2972: 'no_arrf':
template parameter 'unnamed-parameter':
the type of non-type argument is invalid
我可能会认为整个故事对某些人来说可能看起来很琐碎甚至没有用。但是,我相信许多好人会出于急需的标准C 建议。对于他们来说,这既不是微不足道的也不是无用的。
非常感谢您的阅读。
相关文章:
- 如何在 assert() 和 static_assert() 之间调度,如果在 constexpr 上下文中依赖?
- 我关于函数"Assert"的C++代码有问题
- assert() 在发布模式下充当标识函数吗?
- 如何编写一个接受如下断言消息的自定义断言函数:assert(false) << "assertio
- 我可以禁用 GCC 的 assert() 的 noreturn 属性吗?
- 能够使用debug.assert()函数需要什么
- (公开简历)ASSERT: "false" in file qasciikey.cpp
- ASSERT: "allArguments.size() == origArgc"
- static_assert在模板或类中,gotcha
- Qt5 - ASSERT: "bytesTransferred == writeChunkBuffer.size()"
- VS2017 MFC Assert: f:ddvctoolsvc7libsshipatlmfcinclude
- C++ EXPECT_EQ & ASSERT inside for loop
- 为什么 MonitoringManager::OnRequestSucceeded() 中的 assert(s_moni
- 如何正确调用 Assert::ExpectException
- 使用 assert 帮助编译器更好地优化
- 自定义"assert"宏,支持逗号和错误消息
- 是否可以有一个零成本assert(),这样代码就不必在调试和发布版本之间进行修改
- 如何在 Google 测试中抑制终止时 assert() 意外触发
- VS2010: assert "vector iterators incompatible" in std::vector.clear()
- boost shared_ptr assert失败,但值不是null