I am trying to define a function using templates and I want the typename to be either int or anEnum (a specific enum I had defined). I have tried the following but I have failed:
template <int | anEnum T> // or <int T, anEnum T> or <int, anEnum T> bool isFunction(const T &aVariable){}
What I am trying to do is to use templates, instead of defining two overloaded functions. I'd prefer the function to be called as the following, without the programmer having to consider the type
isFunction(aVariable) // and not isFunction<int> (aVariable) nor isFunction<anEnum> (aVariable)
Basically, I want this function to be templated for int and aNum types. I have searched for this, but could not find the answer. What may I be missing? Thank you,
You may overload a function template either by a non-template function or by another function template. The function call f(1, 2) could match the argument types of both the template function and the non-template function.
Templates Specialization is defined as a mechanism that allows any programmer to use types as parameters for a class or a function. A function/class defined using the template is called a generic function/class, and the ability to use and create generic functions/classes is one of the critical features of C++.
overloading is used when we have various functions , doing SIMILAR operations . template is used when we have various functions , doing IDENTICAL operations .
You overload a function name f by declaring more than one function with the name f in the same scope. The declarations of f must differ from each other by the types and/or the number of arguments in the argument list.
In addition to non-C++20 answer, if you are, by any chance, able to use C++20 and its concepts
feature, I would suggest you the following implementation:
#include <iostream> #include <concepts> enum class MyEnum { A, B, C }; template <typename T> concept IntegralOrEnum = std::same_as<MyEnum, T> || std::integral<T>; template <IntegralOrEnum T> bool isFunction(T const& aVariable) { return true; } int main() { isFunction(MyEnum::A); isFunction(3); isFunction("my_string"); // error return 0; }
Demo
UPDATE
According to @RichardSmith's comment, here is a more scalable and reusable approach:
template <typename T, typename ...U> concept one_of = (std::is_same_v<T, U> || ...); template <one_of<int, MyEnum> T> bool isFunction(T const& aVariable) { return true; }
There are a couple of ways to accomplish this. All involve using the type_traits
header. You can static assert on the types in question in the body of the function, for instance.
Or, if you need to consider this function among other overloads, a SFINAE technique can be employed.
template<typename T> auto isFunction(const T &aVariable) -> std::enable_if_t<std::is_same<T, int>::value || std::is_same<T,anEnum>::value, bool> { }
This will remove the function from an overload set before it's called if the types don't match. But if you don't need this behavior, a static assertion does allow for a more programmer friendly error message.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With