Reputation: 1807
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.
Upvotes: 10
Views: 1028
Reputation: 1201
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;
}
Upvotes: 3
Reputation: 217135
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>{}); }
Upvotes: 10
Reputation: 545528
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;
}
Upvotes: 8
Reputation: 55887
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;
}
Upvotes: 6