2013-07-24 4 views
0

Я пытаюсь разработать функцию с различным поведением для массивов и указателей. Это может быть достигнуто для классов по частичной специализации, но это не работает с функциями!Различное поведение функции для массивов и указателей

int i = 0; 
some_func(&i); // pointer 
int arr[ 3 ] = { 0 }; 
some_func(arr); // array 

Во втором случае внутри функции some_func типа параметра является int*, и нет никакого способа узнать, что это на самом деле int[3].

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

template< typename T > 
struct S 
{ 
    static void some_func(T t) { ... } 
}; 

template< typename T, size_t N > 
struct S< T[ N ] > 
{ 
    static void some_func(T t[ N ]) { ... } 
}; 

// ............... 

int arr[ 3 ] = { 0 }; 
S< int[ 3 ] >::some_func(arr); // Works, 
// but specifying type explicitly is not convenient 

Сейчас я решила проблему с макро определить (чтобы быть точным, я нужен только точный sizeof для массивов).

Есть ли способ решить эту проблему, не обращаясь к темной стороне макроопределений?

+0

Это, предположительно, то, что «std :: array» было изобретено для решения. –

+0

К сожалению, я не могу использовать C++ 11. –

+0

Затем используйте 'std :: tr1 :: array', в C++ 98. –

ответ

2

Здесь я использую C++ 11 стиль программирования в C++ 03, чтобы сделать SFINAE и отправить свои массивы на одной перегрузки, и не-массивов на другой:

#include <iostream> 

struct false_type { enum { value = false }; }; 
struct true_type { enum { value = true }; }; 

template<typename T> 
struct is_array:false_type {}; 
template<typename T, std::size_t N> 
struct is_array<T[N]>:true_type {}; 

template<bool b,typename T=void> 
struct enable_if {}; 
template<typename T> 
struct enable_if<true, T> { typedef T type; }; 

template<typename T> 
typename enable_if< is_array<T>::value>::type some_func(T& array, int unused=0) 
{ 
    std::cout << "array\n"; 
} 

template<typename T> 
typename enable_if< !is_array<T>::value>::type some_func(T const& not_array) 
{ 
    std::cout << "pointer\n"; 
} 

int main() { 
    int x[3]; 
    some_func(x); 
    int y; 
    some_func(&y); 
} 
+0

Thanx! Это оно! –

5

Возьмите массив by reference:

template< typename T > 
void some_func(T *t) { ... } 

template< typename T, size_t N > 
void some_func(T (&t)[ N ]) { ... } 
+0

Эти перегрузки будут неоднозначными, хотя:/Распад массива к указателю подвергается специальной обработке при разрешении перегрузки. Это трясина сосать. –

+0

Да, неоднозначный. –

+0

Weird, [g ++ 4.3.2] (http://ideone.com/BqGQQR) дает ошибку двусмысленности, но [g ++ 4.7.2] (http://ideone.com/9miZPu) компилирует (и работает) отлично. И если вы замените 'void some_func (T * t)' на 'void some_func (T * const & t)' (взяв указатель _reference-to-const_ вместо значения), то оба [g ++ 4.3.2] (http: //ideone.com/9ZF5XV) и [g ++ 4.7.2] (http://ideone.com/jBUOnN) принять его ... Имеет ли кто-нибудь Кланг под рукой? =) –

Смежные вопросы