2009-11-17 4 views
8

у меня есть следующий код, используя шаблоны и размер массива в качестве параметра шаблона не типаC++ параметр шаблона в размерности массива

template<int n> double f(double c[n]); 
... 
double c[5]; 
f<5>(c); // compiles 
f(c); // does not compile 

не компилятор, чтобы иметь возможность создать экземпляр второго п без явного параметра шаблона? Я использую g ++ 4.1.

+0

MSVC позволит вам уйти с убийством. –

+0

VC8 не будет - по крайней мере, не с нормальными настройками :) –

+0

Я ошибся. MSVC позволяет вам делать double (& c) [n], что, очевидно, не то же самое. Комо тоже круто с двойным (& c) [n]. Удивительная разница, которую сделают несколько парнеров. –

ответ

28

Он работает при использовании ссылки:

template<size_t n> double f(double (&c)[n]); 
+0

спасибо, что это именно то, что мне нужно – Anycorn

1

К сожалению нет, потому что, когда вы передаете double c[5] в f() или любой массив любой функции, которая принимает массив, если вы потеряете информацию о размере. Вы передаете указатель.

Редактировать: Но см. Ответ gf для обходного пути.

+2

Ваш комментарий, хотя и правильный, не имеет отношения. Правда, во время выполнения нет способа определить размер массива, но вычет параметра шаблона происходит во время компиляции. Компилятор знает, что размер массива равен 5 и может соответствующим образом вывести параметр шаблона, хотя есть некоторые ограничения на это. – boycy

+0

Во время выполнения нет возможности определить оригинальный объявленный тип * любого * примитива. Вы теряете информацию, когда передаете ее функции, которая ожидает указатель, но вы теряете ее так же, как вы теряете информацию, когда вы передаете float функции, которая ожидает целое число. Чтобы быть более конкретным, тип массива во время объявления представляет собой «массив из 5 удвоений» или double [5]. Тип массива размера имеет неявный приведение к указателю. Это приведение настолько распространено, что мы склонны забывать, что это не оригинальный тип массива, но он такой же действительный, как и любой другой. –

0

нет, потому что в другом вызове аргумент может происходить откуда угодно. компилятор наверняка не сможет преследовать ваши указатели во время выполнения.

редактировать: Кстати, это работает для меня, но требует -std = C++ 0x (я использую GCC 4.4)

#include <iostream> 

template <int n> 
struct T 
{ 
    T& 
    operator=(double const cc[n]) 
    { 
     c = cc; 
     return *this; 
    } 
    const double 
    operator[](int const &i) 
    { 
     return c[i]; 
    } 
    double c[n]; 
}; 

template<int n> 
double 
f(T<n> & x) 
{ 
    return x[n-1]; 
} 

int 
main() 
{ 
    T<5> t5 = {10, 20, 30, 40, 50}; 
    T<3> t3 = {100, 200, 300}; 
    std::cout << f(t5) << std::endl; 
    std::cout << f(t3) << std::endl; 
    return 0; 
} 
-1

Это может помочь вам с вашей большой проблемой (что бы это ни было). Это позволит вам запрашивать размер/тип массива при компиляции.

template < typename T_, unsigned N_ > 
class many { 
public: 
    typedef T_ T; 
    enum { N = N_ }; 

    T array[N]; 
}; 

Джастин

+0

Э? Как это помогает? – bobbogo