Как я могу использовать черты типа, чтобы сделать преобразование между массивами и указателями однозначным?
Я хотел бы различать статические массивы и указатели.
Следующий пример не удается скомпилировать из-за конверсий между массивами и указателями с точным соответствием, что делает как foo
возможных кандидатов.
Могу ли я получить 2-ю перегрузку foo
для однозначного выбора с использованием свойств типа?
#include <iostream>
template<typename T>
void foo(const T* str)
{
std::cout << "ptr: " << str << std::endl;
}
template<typename T, size_t N>
void foo(const T (&str)[N])
{
std::cout << "arr: " << str << std::endl;
}
int main()
{
foo("hello world"); // I would like the array version to be selected
return 0;
}
Ответы
Ответ 1
template<typename T>
typename std::enable_if<std::is_pointer<T>::value,void>::type
foo(const T str)
{
std::cout << "ptr: " << str << std::endl;
}
template<typename T, size_t N>
void
foo(const T (&str)[N])
{
std::cout << "arr: " << str << std::endl;
}
Ответ 2
Вы можете использовать следующее:
namespace detail
{
template <typename T> struct foo;
template <typename T>
struct foo<T*>
{
void operator()(const T* str) {std::cout << "ptr: " << str << std::endl;}
};
template <typename T, std::size_t N>
struct foo<T [N]>
{
void operator()(const T (&str)[N]) {std::cout << "arr: " << str << std::endl;}
};
}
template<typename T>
void foo(const T& t)
{
detail::template foo<T>()(t);
}
Живой пример