The struct Vec has all the requirements to be std::default_initializable. But the declaration is not finished, so it failed to compile.
template <std::default_initializable A>
struct It {};
struct Vec {
using Iterator = It<Vec>;
};
Is there some sort of workaround to keep the It requirement ?
In general, the answer to your question is no. If you want to make a member type alias, it has to be known at the time in question. And if the template you're trying to instantiate requires that the type it is given is complete (which default-initializable does), then it must be complete.
In your specific case however, it's not really necessary to make Iterator a member. If you want the iterator type for a range, the correct way to do that is to use ranges::iterator_t. And that meta-function will return the type that ranges::begin() returns.
Your begin member function can be specified to return auto, such that the definition of the function is what provides the It<Vec>, as follows:
template <std::default_initializable A>
struct It {};
struct Vec
{
auto begin() {return It<Vec>(...);}
};
That having been said, even if you want to define your iterator type outside of the container/range that it serves, it is still bound to that container/range type. Unless It is some kind of view or range transformation (and if it is, it probably shouldn't be default-constructing the range it modifies), It<UserType> shouldn't work. As such, constraining the It template is pointless; you know that Vec is default constructible because you wrote that class just below the iterator. If you want a sanity check, you can use a static_assert, but you don't need to constrain the template itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With