8

I have have the following code using templates and array dimension as template non-type parameter

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

should not the compiler to be able to instantiate the second f without explicit template parameter? I am using g++4.1

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Anycorn
  • 50,217
  • 42
  • 167
  • 261

4 Answers4

30

It works when using references:

template<size_t n> double f(double (&c)[n]);
Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
1

Unfortunately no, because when you pass double c[5] to f(), or any array to any function which takes an array for that matter, you lose the size information. You are only passing a pointer.

Edit: But see gf's answer for a workaround.

Charles Salvia
  • 52,325
  • 13
  • 128
  • 140
  • 2
    Your comment, whilst correct, is unrelated. True, at runtime there is no way to determine the size of an array, but template parameter deduction occurs at compile-time. The compiler knows that the size of the array is 5 and can deduce the template parameter accordingly, though there are some limitations on that. – boycy Aug 17 '11 at 12:45
  • There's no way at runtime to determine the original declared type of *any* primitive. You do lose information when you pass it to a function that expects a pointer, but you lose it in the same way that you lose information when you pass a float to a function that expects an integer. To be more specific, the type of the array at declaration time is "array of 5 doubles", or double [5]. The sized array type has an implicit cast to a pointer. This cast is so common that we tend to forget it isn't the original type of the array, but it's just as valid a type as any other. – Ian Ni-Lewis Sep 30 '15 at 20:10
0

no, because in a different call, the argument might be coming from wherever. the compiler surely cannot chase your pointers at runtime.

edit: btw, this works for me, but requires -std=c++0x (I'm using 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;
}
just somebody
  • 18,602
  • 6
  • 51
  • 60
  • I'm specifically asking about the multi-dimensional case. There are additional things going on there that aren't present in the single dimension case. It seems easy enough to infer "int arr[N]" but "int arr[N][M]" is too difficult. – Nathan Doromal Apr 27 '18 at 04:26
-1

This could help you with your larger problem (whatever that may be). This will allow you to query the size/type of the array at compilation.

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

    T array[N];
};

Justin

justin
  • 104,054
  • 14
  • 179
  • 226