можно ли сделать эти шаблоны однозначными - PullRequest
2 голосов
/ 23 мая 2010

Я пытаюсь создать набор перегруженных шаблонов для массивов / указателей, где один шаблон будет использоваться, когда компилятор знает размер массива, а другой шаблон будет использоваться, когда он не:

template <typename T, size_t SZ>
void moo(T (&arr)[SZ])
{ ... }

template <typename T>
void moo(T *ptr)
{ ... }

Проблема в том, что когда компилятор знает размер массива, перегрузки неоднозначны и компиляция завершается неудачей.

Есть ли какой-нибудь способ устранить неоднозначность (возможно, через SFINAE) или это просто невозможно?

Ответы [ 3 ]

5 голосов
/ 23 мая 2010

Это возможно, поскольку можно определить, является ли параметр шаблона массивом или нет:

template<class T> struct is_array {
    enum { value = false }; 
};
template<class T, size_t N> struct is_array<T[N]> {
   enum { value = true }; 
};
template<class T> void f(T const&) { 
    std::cout << is_array<T>::value << std::endl;
}

Сочетая это с enable_if, вышеприведенное можно сделать однозначным. Например, используя Boost.TypeTraits:

template <typename T, size_t SZ>
typename boost::enable_if<boost::is_array<T>, void>::type
f(T (&arr)[SZ]) {}

С ссылками, однако, SFINAE вообще не требуется:

template<class T, size_t SZ> void f(T (&arr)[SZ]) {}
template<class T>            void f(T* const& t)  {}

Йоханнес предлагает еще одну опцию, которая лучше подходит к данной ситуации - вместо этого используется SFINAE для проблемной перегрузки указателя:

template <typename T, size_t SZ> void f(T (&arr)[SZ]) {}
template <typename T>
typename boost::enable_if<boost::is_pointer<T>, void>::type
f(T ptr) {}
2 голосов
/ 10 марта 2011

И, наверное, самое простое решение:

template <typename T, size_t SZ>
void moo(T (&arr)[SZ])
{ ... }

template <typename T>
inline void moo(T ptr) { __moo(ptr); }

template <typename T>
void __moo(T* ptr)
{ ... }
0 голосов
/ 23 мая 2010

Вы можете вызвать функцию явно:

int a[1] = {0}
moo<int,1>(a);

Или вы можете перегрузить на const:

template<class T>
void moo(T const* p) { }

// ...
moo(a); // not const, array

int* p = 0;
moo(p); // pointer
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...