考虑以下代码:
#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移到类之外,那么它编译得很好,但在类内部则不然。相反,如果类具有模板类型,则情况正好相反。
当DeepNodeIter
是模板类时,为什么我在这里得到错误,为什么我没有得到它?
当您将DeepNodeIter
作为模板时,它实际上也不会编译:https://godbolt.org/z/W9jf94xPn
它看起来可能起作用的原因是,如果你没有实例化模板,编译器就不会主动失败编译,因为你可能会在实例化模板之前专门化它。
这不起作用的原因是,一个类型在达到其右大括号之前被认为是不完整的。在此之前,就好像您只有一个类型的声明,即class DeepNodeIter;
。这个规则有一些例外,比如在被编译的定义中定义的成员函数,就好像它们就在类定义之后一样,但显然static_assert
s没有。