'How do I add templates to a static_assert?
Consider the following code:
#include <iterator>
struct Node {
static Node mNode;
};
Node Node::mNode;
struct DeepNodeRange {};
template<class T>
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) {}
auto operator*() const { return &Node::mNode; }
auto& operator++()
{
mIdx++;
mEnd = (mIdx > 10);
return *this;
}
auto operator++([[maybe_unused]] int val)
{
auto tmp(*this);
operator++();
return tmp;
return tmp;
}
auto operator==(const DeepNodeIter& iter) const
{ return iter.mEnd == mEnd; }
protected:
DeepNodeRange* mDeepNodeRange;
int mIdx;
bool mEnd;
};
template<class T>
static_assert(std::forward_iterator<DeepNodeIter<T>>);
int main() {
}
I get the following error:
b.cpp:54:1: error: expected unqualified-id before 'static_assert'
54 | static_assert(std::forward_iterator<DeepNodeIter<T>>);
| ^~~~~~~~~~~~~
./b.out: Command not found.
I had the static_assert in the class definition before but it was failing because the return types couldn't be deduced to verify the assertion. Now that it's outside, I lack the template definitions I need for the assert to work. Is there a way to get templates in a static_assert?
Solution 1:[1]
C++ templates are Turing-complete. The full description of Foo<T> can involve nearly arbitrary computation in the general case.
Your assert seems to want to assert something uniformly true about all Foo<T>; this is provably impossible in the general case of template type subsitution.
As a rule, C++ will only allow you to invert the mapping implied by Foo<T> in specific narrow cases, and will not let you do universal qualification over it.
TL;DR put the static assert in the type factory.
template<class T>
class DeepNodeIter{
class DeepNodeIterImpl{ // implement
};
public:
using type=DeepNodeIterImpl;
static_assert(/* blah */);
};
template<class T>
using DeepNodeIter_t=typename DeepNodeIter<T>::type;
that would guarantee a static assert every time you instantiate a DeepNodeIter_t<x>.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Yakk - Adam Nevraumont |
