Everything has a cost, even if it isn't measured in runtime performance.
Encoding such assumptions into the type system sounds like a good idea. But it is not without its flaws. In particular, it requires you to have and use a bunch of increasingly specific types for increasingly specific assumptions.
Let's say that you have a function that takes an array from the user and modifies the first three elements in it. Now, this function makes two assumptions: that there's actually an array and that the array is at least 3 elements long.
There are types which can encode both of these assumptions. The guideline support library type
span can cover both of these. But just look at the code for that type. If it weren't available, you probably wouldn't write it yourself.
The more such assumptions you have, and the more special-case they get, the harder it is to write a type just for them. After all,
span only solves this particular problem as a partial by-product of solving its real problem: having a way to represent an array of some size.
So it's a balancing act. You don't want to spend more time writing special-case types, but you do need some to cover a lot of bases. Where exactly you draw the line depends on your needs, but I don't feel that trying to encode everything into the type system is worthwhile.
Also, having contracts as part of C++, which people are working on (PDF), would be able to bridge the gap here in many of the special cases.
There is also the issue of dealing with combinations of such contracts. The
not_null contract is generally a good idea, but by its very nature it cannot work with move-only types that leave the moved-from object null. Thus,
not_null<unique_ptr<T>> is not a functional type.
Again, that's not to say that you shouldn't have these. But you really need to think about when it is truly appropriate to have a type encapsulate a contract and when it is not.