0

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?

11
  • 2
    +1 for a good question (though I don't think it is a good idea).
    – Doc Brown
    Feb 1, 2021 at 17:30
  • This is what the type trait enable_if is for (especially when combined with operator !). There is already plenty of code that uses this technique - you can easily find it and learn the many ways to use it. In fact, check this tutorial out.
    – davidbak
    Feb 1, 2021 at 18:21
  • @DocBrown That's why I post them here because they are only concepts. It's to gain insight from the community at large to see the pros and cons of possible concepts. Feb 1, 2021 at 18:21
  • 1
    @NicolBolas This is a Q/A for Software Engineering, doesn't compiler design, language features fall under that category? Feb 1, 2021 at 18:28
  • 1
    @NicolBolas: I think it very case dependent if questions about potential new language features are acceptable for this site. They are definitely not off-topic, but there is always a certain risk for them to be too opinionated or open ended. In this case, however, I think the question can be answered in a straightforward way why the suggested feature is not as good as it might look at a first glance. Hence I don't see any reason to refuse it.
    – Doc Brown
    Feb 1, 2021 at 20:11

2 Answers 2

6

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.

1
  • 1
    I like the way you expressed your position and point of view. It portrays a sense of negative criticism in a positive way, instead of negative criticism in a negative way. Very informative instead of just stating that it can be done in another way. You clearly explain why the existing functionality is a better approach and describing where you could encounter the unforeseen drawbacks that would cause it to fail, leading to future problems. Feb 1, 2021 at 18:19
0

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;
};
8
  • Yes, but what looks easier to read and cleaner? What uses less code or instructions? Not having to include the library for std::is_same<T>... I'm looking at code simplification just by allowing the declaration of the template itself to handle this for you upon compilation just by incorporating the use of the ! or != operators on that argument type <T>. You also wouldn't have static_assert cluttering the declaration of your class template... faster compile times... Feb 1, 2021 at 14:01
  • @FrancisCugler This is much more flexible, you can have any constexpr bool in the assert
    – Caleth
    Feb 1, 2021 at 14:04
  • I'm not saying to do away with static_assert and is_same... but to "streamline" this process by providing it as a built-in feature upon compilation & class template instantiation... Making it an alternative, and another useful tool. Feb 1, 2021 at 14:06
  • 2
    @FrancisCugler there is no runtime overhead here, it's all evaluate at compile time. Also, why add even more confusing syntax to a language when the stdlib can express the same concepts and even more concepts better? If you have to exclude types from templates so often that you'll benefit from the conciseness i guess you're sort of on the wrong track.
    – marstato
    Feb 1, 2021 at 14:35
  • 3
    @FrancisCugler - the C++ language designers - and many many C++ users - have a philosophy of what gets added - syntax-wise especially, but also as standard libraries - to an already complex language, and what gets left out. Except for concepts, mostly everything to do with template syntax is just the way it is, and it is all accepted. Yes, metaprogramming with template syntax is baroque, at best, but that's the language we've got and the language we're going to have. Concepts, though, added in C++20, are a major change for the better - and it took well over a decade to get it in ...
    – davidbak
    Feb 1, 2021 at 18:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.