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

3
  • MSVC will let you get away with murder. Commented Nov 17, 2009 at 1:06
  • VC8 won't - at least not with sane settings :) Commented Nov 17, 2009 at 1:08
  • I was mistaken. MSVC lets you do double (&c)[n] which is obviously, not the same thing. Comeau is also cool with double (&c)[n]. Amazing the difference a few parens will make. Commented Nov 17, 2009 at 1:10

4 Answers 4

30

It works when using references:

template<size_t n> double f(double (&c)[n]); 
Sign up to request clarification or add additional context in comments.

Comments

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.

2 Comments

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.
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.
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; } 

1 Comment

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.
-2

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

1 Comment

Eh? How does this help?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.