Built-in types (as well as types from std) are used everywhere as parameters to functions and constructors while not every instance of those types would be valid inputs.
Examples:
// There is no guarantee that url is actually a url
void make_http_request(const std::string& url);
// Here we know that it must be a url
void make_http_request(const url& url);
// There is no way of knowing if this is the correct mutex to lock
void insert_into_db(std::mutex mutex);
// Here we know we have the correct mutex
void insert_into_db(db_mutex mutex);
This of course should never be used for attributes of an object that you don't have control over. For example, you could make a class connected_socket
but if the peer closes the connection the class becomes a fallacy. However it could be used to ensure that an IPv4 UDP socket never tries to sendto()
an IPv6 endpoint.
The more you do this the more you can ensure your program is valid at compile time (and who doesn't like that?). Is there anything wrong with this practice and would it be considered good? What are the downsides and would they worth it?
Forgive me if this is a concept that goes by another name and I have just not been able to find it.
There is guideline in the C++ Core Guidelines about this:
I.4: Make interfaces precisely and strongly typed
Reason
Types are the simplest and best documentation, have well-defined meaning, and are guaranteed to be checked at compile time. Also, precisely typed code is often optimized better.
It gives some examples. It doesn't really talk about how far is too far though.