I'd like to supply two forms of a GetLength(psz)
style function - one that doesn't know an upper bounds, and one that does:
template <typename T>
size_t GetLength(const T * psz) { /* compute size w/o knowing what upper bound may be */ }
template <typename T, size_t size>
size_t GetLength(const T(&psz)[size]) { /* we know the upper bound */ }
I'd like that this not be ambiguous. I want the array-sized version to be chosen when the argument is an array of known size. I want the unbounded version chosen when the argument is just a pointer, not a known fixed array.
I'd also offer a 3rd version which explicitly takes the upper bounds as an argument, without templated size deduction, for passing that info in from an outer context which has otherwise lost the ability to deduce that from its local arguments.
Is there a technique I can use to force the compiler to discount the 1st version of my function (no known bounds) when the bounds is known?
We could use type traits:
#include <type_traits>
// If T is an array
template<
typename T,
typename std::enable_if <
std::is_array<T>{},
size_t
> ::type Extent = std::extent<T>::value
>
size_t GetLength(const T& t)
{
return Extent;
}
// If T is not an array
template<typename T,
typename std::enable_if <
!std::is_array<T>{},
size_t
> ::type = 0
>
size_t GetLength(const T& t)
{
return {};
}
int main()
{
int arr[5]{};
GetLength(arr); // calls first
//decay to pointer
auto val = arr;
GetLength(val); // calls second
}