Let's say, we need a function template which should return an integer depending on a type:
template<typename T>
int get_type();
Further, we do specialize it with couple of types:
template<>
int get_type<int>()
{
return TYPE_INT;
}
// And so on for other types...
And this works well, but not for array types. I can do the following:
template<>
int get_type<char[]>()
{
return TYPE_STRING;
}
and compiler "agrees" with this, but linker does not. Because the type char[]
differs against, for example, the char[5]
.
Is there any way to implement this function template without function parameters? I.e., I know that we can do something like this:
template<typename T>
int get_type(const T&);
But, actually the function parameter is not needed (used) here.
EDIT:
I use the C++ 11.
To do so, we can use a function template specialization (sometimes called a full or explicit function template specialization) to create a specialized version of the print() function for type double.
Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
Defining a Function Template In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword. When an argument of a data type is passed to functionName() , the compiler generates a new version of functionName() for the given data type.
You cannot partial specialize template functions (but you can for template classes)
Another approach is tag dispatching with overloads, instead of specialization:
template <typename> struct Tag{};
constexpr int get_type(Tag<int>) { return TYPE_INT; }
template <std::size_t N>
constexpr int get_type(Tag<char[N]>) { return TYPE_STRING; }
template <typename T>
constexpr int get_type() { return get_type(Tag<T>{}); }
You need a partial specialisation to account for variable array lengths, and C++ does not allow partially specialised function templates. The canonical solution is to (partially) specialise a class template with a (static) member (function), and dispatch to that from within your unspecialised function template:
namespace detail {
template <typename T>
struct get_type;
template <>
struct get_type<int> {
static constexpr int value = TYPE_INT;
};
template <>
struct get_type<char> {
static constexpr int value = TYPE_CHAR;
};
template <typename T, std::size_t N>
struct get_type<T[N]> {
static constexpr int value = get_type<T>::value | TYPE_ARRAY;
};
template <std::size_t N>
struct get_type<char[N]> {
static constexpr int value = TYPE_STRING;
};
} // namespace detail
template<typename T>
constexpr int get_type() {
return detail::get_type<T>::value;
}
You can't partially specialize function for array with size. But you can do it with class.
template<typename T>
class type
{
static int get_type();
};
template<>
struct type<int>
{
static int get_type() { return 1; }
};
template<size_t SZ>
struct type<char[SZ]>
{
static int get_type() { return 2; }
};
template<typename T>
int get_type() { return type<T>::get_type(); }
int main()
{
std::cout << get_type<char[3]>() << std::endl;
return 0;
}
example
Konrad already described the best approach in my opinion.
Here is another approach with overloads and specialization powered by SFINAE
// overload 1, for non-array types
template<typename T>
std::enable_if_t<!std::is_array_v<T>, int> get_type();
// specialization of overload 1 for int
template <>
auto get_type<int>() -> int {
return 1;
}
// overload 2, for array types
template <typename T>
auto get_type() -> std::enable_if_t<std::is_array_v<T>, int> {
return 3;
}
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