Question

When using templates we can have T be any type upon class instantiation. If T is a specific type that needs to be handled differently or in a special way we can specialize or partial specialize that class template.

What if we want T to be any type except for specific types that we don't want it to allow?

With this in mind, I was thinking of making use of either the ! or != operator(s) or more as them being tokens within this context as far as the compiler(s) would be concerned to prevent the class template from using that type...

Here's an example of what the syntax would look like:

template<typename T, T !=char, T !=unsigned char>
// or 
template<typename T, T !char, T !unsigned char>
// This means that T can be anything but char and unsigned char!
struct Foo {
    T value;
};

Then:

Foo<int> f1;   // Okay
Foo<float> f2; // Okay
Foo<char> f3;  // Would fail to compile generating the appropriate error message or 
               // would just delete that instance as if it was never declared
               // and generate compiler errors for all code that would try to use it.

This could also be extended or expanded to work with user-defined types as well...

I believe that this could allow for simplifying a lot of code allowing the programmer to explicitly fine-tune and restrict their code usage to their users, that it is easy to read with direct intent shown, and that it would be fairly easy for the compilers to implement without breaking already existing code bases by adding in this feature.

Would this be something that you would find useful and practical?

Was it helpful?

Solution

Why would it make sense to forbid specificially named types in template parameters (without a template specialization)? The only real reason I can imagine is that the forbidden type would cause some issues in the template, probably some issues the compiler cannot determine directly. For example, char might not be used, because its range is not large enough for the specific purpose, but that would only reveal itself at runtime.

However, this kind of check can too easily become pointless when the forbidden type is wrapped inside in another type, like

struct Bar{ char MyChar; }

which has essentially the same type traits as char. So the same reasons for using char as a parameter would apply to Bar as well, but the type exclusion would not catch it.

Hence, I think it would make a lot more sense to check the required type traits directly for finding out if a certain type is suitable for usage in a template or not. This would be also way more readable, since it shows more clearly why a certain type shall be not allowed. For this, the suggested syntax would be not not sufficient, a static_assert together with using tools from <type_traits> makes IMHO more sense.

OTHER TIPS

You can already do this, with a static_assert in your template.

template<typename T>
struct Foo {
    // This means that T can be anything but char and unsigned char!
    static_assert(!std::is_same_v<T, char>);
    static_assert(!std::is_same_v<T, unsigned char>);
    T value;
};
Licensed under: CC-BY-SA with attribution
scroll top