I have a base class that is intended to be inherited by other users of the code I'm writing, and one of the abstract functions returns a name for the object. Due to the nature of the project that name cannot contain whitespace.
class MyBaseClass {
public:
// Return a name for this object. This should not include whitespace.
virtual const char* Name() = 0;
};
Is there a way to check at compile-time if the result of the Name() function contains whitespace? I know compile-time operations are possible with constexpr functions but I'm not sure of the right way to signal to code users that their function returns a naughty string.
I'm also unclear on how to get a constexpr function to actually be executed by the compiler to perform such a check (if constexpr is even the way to go with this).
I think this is possible in C++20.
Here is my attempt:
There are several ideas at play here:
Let's use the type system as documentation as well as constraint. Therefore, let us create a class (
no_wsin the above example) that represents a string without whitespaces.For the type to enforce the constraints at compile-time, it must evaluate its constructor at compile time. So let's make the constructor
consteval.To ensure that derived classes don't break the contract, modify the virtual method to return
no_ws.If you want to keep the interface (i.e returning
const char*), make the virtual method private, and call it in a public non-virtual method. The technique is explained here.Now of course here I am only checking a finite set of whitespace characters and is locale-independent. I think it would very tricky to handle locales at compile-time, so maybe a better way (engineering-wise) would be to explicitly specify a set of ASCII characters allowed in the names (a whitelist instead of a blacklist).
The above example would not compile, since
"Bad cat"contains whitespace. Commenting out theBad catclass would allow the code to compile.Live demo on Compiler Explorer