为什么static_assert需要在类定义的一边?
失败的代码
#include <type_traits>
class A
{
public:
A(A&&) noexcept {}
static_assert(std::is_nothrow_move_constructible<A>::value, "ERROR");
};
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
工作代码
#include <type_traits>
class A
{
public:
A(A&&) noexcept {}
};
static_assert(std::is_nothrow_move_constructible<A>::value, "ERROR");
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
什么时候在类或结构的定义中使用static_assert是否合适?
我想这样做可能效率低但不一定不正确的用法.
我之前根据参数是否constexpr询问函数重载.我正试图解决这个问题的令人失望的答案,以建立一个更聪明的断言功能.这大致是我想做的事情:
inline void smart_assert (bool condition) {
if (is_constexpr (condition))
static_assert (condition, "Error!!!");
else
assert (condition);
}
Run Code Online (Sandbox Code Playgroud)
基本上,我们的想法是编译时检查总是比运行时检查更好,如果可以在编译时检查.但是,由于内联和常量折叠之类的东西,我不能总是知道是否可以进行编译时间检查.这意味着可能存在assert (condition)编译的情况,assert(false)代码只是等待我运行它并在我发现错误之前执行该路径.
因此,如果有某种方法来检查条件是否是constexpr(由于内联或其他优化),我可以static_assert在可能的情况下调用,否则返回运行时断言.幸运的是,gcc具有内在函数__builtin_constant_p (exp),如果exp是constexpr 则返回true .我不知道其他编译器是否有这种内在的,但我希望这可以解决我的问题.这是我提出的代码:
#include <cassert>
#undef IS_CONSTEXPR
#if defined __GNUC__
#define IS_CONSTEXPR(exp) __builtin_constant_p (exp)
#else
#define IS_CONSTEXPR(exp) false
#endif
// TODO: Add other compilers
inline void smart_assert (bool const condition) {
static_assert (!IS_CONSTEXPR(condition) or condition, "Error!!!");
if (!IS_CONSTEXPR(condition))
assert (condition);
}
#undef IS_CONSTEXPR
Run Code Online (Sandbox Code Playgroud)
该static_assert …
考虑以下情况
typedef void (*foo)();
template<foo f>
struct bar {
static_assert(f!=nullptr,"f == null!");
};
void baz() {}
inline void bax() { }
bar<baz> ok;
bar<bax> bad; // error: non-constant condition for static assertion
Run Code Online (Sandbox Code Playgroud)
这两个baz和bax被接受为模板参数.它表明两者都被接受为常量.然而,static_assert它们似乎是不同的(至少在gcc 4.9中) - bax不再是常数.
我的假设是static_assert和模板相同地评估常数.例如,错误应该是
static_assert 不应该引起非恒定条件错误.我错了吗?
我构建了一个帮助类,它将通过模板构建一个自定义类,这个自定义类必须从某个类继承,我可以检查这个std::is_base_of.
但是我还需要检查继承是否公开,如何实现?
作为参考,这里是一个精简版的课程,我std::is_base_of在那里.
template<class CustomSink>
class Sink
{
static_assert(std::is_base_of<BaseSink, CustomSink>::value, "CustomSink must derive from BaseSink");
//Some static assert here to check if custom sink has publicly inherited BaseSink
//static_assert(is_public.....
public:
template<class... Args>
Sink(Args&&... args)
{
}
~Sink()
{
}
};
Run Code Online (Sandbox Code Playgroud) 我完全明白为什么这不能正常工作:
class Base {};
class A;
static_assert(std::is_base_of<Base, A>::value, "");
Run Code Online (Sandbox Code Playgroud)
因为没有关于"类层次结构"的信息,但是......为什么以下不能工作?
class Base {};
class A : public Base {
static_assert(std::is_base_of<Base, A>::value, "");
};
(produce: an undefined class is not allowed as an argument to compiler intrinsic type trait)
Run Code Online (Sandbox Code Playgroud)
类型'A'仍然没有与static_assert一致(根据这个概念的定义).但是 - 编译器已经知道'类层次结构'并且可以为此提供答案.
当然 - 这个static_assert可以移动到析构函数或其他什么来解决这个问题,但有些情况下无法完成,例如:
class Base {};
template<typename T>
struct type_of {
static_assert(std::is_base_of<Base, T>::value, "T is not derived from Base");
using type = int; //* Some normal type in real use
};
class A : public Base { …Run Code Online (Sandbox Code Playgroud) 当我们想在 astatic_assert中使用 a 时,if constexpr我们必须使条件依赖于某个模板参数。有趣的是,当代码包含在 lambda 中时,gcc 和 clang 不同意。
以下代码使用 gcc 进行编译,但 clang 会触发断言,即使if constexpr不能为真。
#include <utility>
template<typename T> constexpr std::false_type False;
template<typename T>
void foo() {
auto f = [](auto x) {
constexpr int val = decltype(x)::value;
if constexpr(val < 0) {
static_assert(False<T>, "AAA");
}
};
f(std::integral_constant<int, 1>{});
}
int main() {
foo<int>();
}
Run Code Online (Sandbox Code Playgroud)
它可以很容易地通过用固定False<T>通过False<decltype(x)>。
所以问题是:哪个编译器是正确的?我认为 gcc 是正确的,因为 中的条件static_assert取决于T,但我不确定。
我一直在尝试实现类似于static_assertC++ 11标准中定义的方法.主要问题是C++编译器如何将传递给的文本消息static_assert写成const char*?我可以让编译器写一个像这样的消息A_is_not_POD.这就是我所拥有的:
#define MY_STATIC_ASSERT(condition, name) \
typedef char name[(condition) ? 1 : -1];
Run Code Online (Sandbox Code Playgroud)
但是让编译器编写类似"Error: A is not POD."Any建议的东西会很好吗?
请考虑以下代码:
template <unsigned int N>
struct myclass
{
unsigned int f() {return N;}
unsigned int g() {static_assert(N > 0, ""); return N-1;}
};
Run Code Online (Sandbox Code Playgroud)
问题:我是否保证以下代码将编译:
myclass<0> c;
c.f();
Run Code Online (Sandbox Code Playgroud)
但以下不会:
myclass<0> c;
c.f();
c.g();
Run Code Online (Sandbox Code Playgroud) #include <cstddef>
template<typename... Types>
constexpr std::size_t getArgCount(Types&&...) noexcept
{
return sizeof...(Types);
}
struct A
{
int n;
void f()
{
static_assert(getArgCount(n) > 0); // not ok, why?
}
};
int main()
{
int n;
static_assert(getArgCount(n) > 0); // ok
}
Run Code Online (Sandbox Code Playgroud)
为什么在编译时无法获得模板函数的参数计数?
错误信息:
1>test.cpp
1>test.cpp(17,45): error C2131: expression did not evaluate to a constant
1>test.cpp(17,42): message : failure was caused by a read of a variable outside its lifetime
1>test.cpp(17,42): message : see usage of 'this'
Run Code Online (Sandbox Code Playgroud) c++ ×10
static-assert ×10
c++11 ×7
constexpr ×2
inline ×2
templates ×2
type-traits ×2
c++17 ×1
c99 ×1
class ×1
compile-time ×1
function ×1