Подтвердить что ты не робот

Как я могу использовать черты типа, чтобы сделать преобразование между массивами и указателями однозначным?

Я хотел бы различать статические массивы и указатели.

Следующий пример не удается скомпилировать из-за конверсий между массивами и указателями с точным соответствием, что делает как 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;
}
4b9b3361

Ответ 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);
}

Живой пример