I would say it is possible based on C++20 iterator concepts1:
template<std::input_iterator T>
using validate_input_iterator = T;
This would fail compilation:
struct meow {
struct iterator{};
private:
typedef validate_input_iterator<iterator> v; // fails here
};
However the below compiles:
struct meow: private std::string { // string has an input iterator
// struct iterator{};
private:
typedef validate_input_iterator<iterator> v; // passes!
};
https://godbolt.org/z/5DwiaT
If you actually want to check you implemented the required functions and traits correctly, this would of course couldn't be checked at compile time and requires writing some tests.
Syntactic requirements vs. Semantic requirements
Note that concepts, and specifically iterator concepts, declare both syntactic requirements and semantic requirements. While the syntactic requirements, stated based on the requires
syntax, can be statically checked at compile time, the semantic requirements that are merely "notes" to be followed by that type, are not and cannot be checked at compile time. On the other hand algorithms and compiler decisions may be based on the fact that a type said to implement a specific concept follows its semantic requirements.
For example, bidirectional_iterator
is defined as:
23.3.4.12 Concept bidirectional_iterator [iterator.concept.bidir]
- The
bidirectional_iterator
concept adds the ability to move an iterator backward as well as forward.
template<class I>
concept bidirectional_iterator =
forward_iterator<I> &&
derived_from<ITER_CONCEPT(I), bidirectional_iterator_tag> &&
requires(I i) {
{ --i } -> same_as<I&>;
{ i-- } -> same_as<I>;
};
A bidirectional iterator r
is decrementable if and only if there exists some q
such that ++q == r
. Decrementable iterators r
shall be in the domain of the expressions --r
and r--
.
Let a
and b
be equal objects of type I
. I
models bidirectional_iterator
only if:
(3.1) If a
and b
are decrementable, then all of the following are true:
(3.1.1) addressof(--a) == addressof(a)
(3.1.2) bool(a-- == b)
(3.1.3) after evaluating both a--
and --b
, bool(a == b)
is still true
(3.1.4) bool(++(--a) == b)
(3.2) If a
and b
are incrementable, then bool(--(++a) == b)
.
For a given iterator said to implement bidirectional_iterator
as seen above, bullet #1 can be checked at compile time while bullets #2 and #3 cannot.
1 Should also be doable pre C++20 implementing your own SFINAE restricted template in a similar manner