static_assert 的最佳去处是什么?
What is the best place for a static_assert?
考虑以下代码:
#include <iterator>
struct Node {
static Node mNode;
};
Node Node::mNode;
struct DeepNodeRange {};
class DeepNodeIter
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Node*;
using difference_type = std::ptrdiff_t;
DeepNodeIter() = default;
DeepNodeIter(DeepNodeRange& deepNodeRange, bool end = false) :
mDeepNodeRange(&deepNodeRange), mEnd(end) {}
Node* operator*() const { return &Node::mNode; }
DeepNodeIter& operator++()
{
mIdx++;
mEnd = (mIdx > 10);
return *this;
}
DeepNodeIter operator++([[maybe_unused]] int val)
{
auto tmp(*this);
operator++();
return tmp;
}
bool operator==(const DeepNodeIter& iter) const { return iter.mEnd == mEnd; }
protected:
DeepNodeRange* mDeepNodeRange;
int mIdx;
bool mEnd;
static_assert(std::forward_iterator<DeepNodeIter>);
};
int main() {
}
我收到以下错误:
In file included from include/c++/11.1.0/bits/stl_iterator_base_types.h:67,
from include/c++/11.1.0/iterator:61,
from b.cpp:1:include/c++/11.1.0/type_traits: In instantiation of 'struct std::is_nothrow_destructible<DeepNodeIter>':
include/c++/11.1.0/type_traits:3166:35: required from 'constexpr const bool std::is_nothrow_destructible_v<DeepNodeIter>'
include/c++/11.1.0/concepts:134:28: required from here
include/c++/11.1.0/type_traits:900:52: error: static assertion failed: template argument must be a complete class or an unbounded array
900 | static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
include/c++/11.1.0/type_traits:900:52: note: 'std::__is_complete_or_unbounded<std::__type_identity<DeepNodeIter> >((std::__type_identity<DeepNodeIter>{}, std::__type_identity<DeepNodeIter>()))' evaluates to false
b.cpp:50:22: error: static assertion failed
50 | static_assert(std::forward_iterator<DeepNodeIter>);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
b.cpp:50:22: note: constraints not satisfied
看来,如果我将 static_assert 移到 class 之外,那么它可以正常编译,但在 class 内部则不能。相反,如果 class 具有模板类型,则反之亦然。
为什么我在这里收到错误消息,为什么当 DeepNodeIter
是模板 class 时我没有收到错误消息?
当你制作 DeepNodeIter
模板时它实际上并没有编译:https://godbolt.org/z/W9jf94xPn
它看起来有效的原因是,如果您没有实例化模板,编译器将不会主动编译失败,因为您可能会在实例化之前专门化模板。
这不起作用的原因是,一个类型在到达它的右大括号之前被认为是不完整的。在那之前,就好像你只有一个类型的声明,即 class DeepNodeIter;
。此规则有一些例外情况,例如定义中定义的成员函数被编译为就好像它们就在 class 定义之后,但显然不是 static_assert
s.
考虑以下代码:
#include <iterator>
struct Node {
static Node mNode;
};
Node Node::mNode;
struct DeepNodeRange {};
class DeepNodeIter
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Node*;
using difference_type = std::ptrdiff_t;
DeepNodeIter() = default;
DeepNodeIter(DeepNodeRange& deepNodeRange, bool end = false) :
mDeepNodeRange(&deepNodeRange), mEnd(end) {}
Node* operator*() const { return &Node::mNode; }
DeepNodeIter& operator++()
{
mIdx++;
mEnd = (mIdx > 10);
return *this;
}
DeepNodeIter operator++([[maybe_unused]] int val)
{
auto tmp(*this);
operator++();
return tmp;
}
bool operator==(const DeepNodeIter& iter) const { return iter.mEnd == mEnd; }
protected:
DeepNodeRange* mDeepNodeRange;
int mIdx;
bool mEnd;
static_assert(std::forward_iterator<DeepNodeIter>);
};
int main() {
}
我收到以下错误:
In file included from include/c++/11.1.0/bits/stl_iterator_base_types.h:67,
from include/c++/11.1.0/iterator:61,
from b.cpp:1:include/c++/11.1.0/type_traits: In instantiation of 'struct std::is_nothrow_destructible<DeepNodeIter>':
include/c++/11.1.0/type_traits:3166:35: required from 'constexpr const bool std::is_nothrow_destructible_v<DeepNodeIter>'
include/c++/11.1.0/concepts:134:28: required from here
include/c++/11.1.0/type_traits:900:52: error: static assertion failed: template argument must be a complete class or an unbounded array
900 | static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
include/c++/11.1.0/type_traits:900:52: note: 'std::__is_complete_or_unbounded<std::__type_identity<DeepNodeIter> >((std::__type_identity<DeepNodeIter>{}, std::__type_identity<DeepNodeIter>()))' evaluates to false
b.cpp:50:22: error: static assertion failed
50 | static_assert(std::forward_iterator<DeepNodeIter>);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
b.cpp:50:22: note: constraints not satisfied
看来,如果我将 static_assert 移到 class 之外,那么它可以正常编译,但在 class 内部则不能。相反,如果 class 具有模板类型,则反之亦然。
为什么我在这里收到错误消息,为什么当 DeepNodeIter
是模板 class 时我没有收到错误消息?
当你制作 DeepNodeIter
模板时它实际上并没有编译:https://godbolt.org/z/W9jf94xPn
它看起来有效的原因是,如果您没有实例化模板,编译器将不会主动编译失败,因为您可能会在实例化之前专门化模板。
这不起作用的原因是,一个类型在到达它的右大括号之前被认为是不完整的。在那之前,就好像你只有一个类型的声明,即 class DeepNodeIter;
。此规则有一些例外情况,例如定义中定义的成员函数被编译为就好像它们就在 class 定义之后,但显然不是 static_assert
s.