Deducing array parameter type and size on template function call

  • Follow


Hi, is there a reason why the compiler cannot deduce an array type
along with its size during template function argument deduction?

For instance:

template <class T, int N> void test(T a[N]) {}

int a[10];
test(a); // test isn't in the overload set, but should (IMHO)

This might be useful to avoid array -> pointer automatic conversion
during function calls.

Regards,
Rodolfo Lima.

--
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Rodolfo 1/24/2009 9:57:37 PM

Rodolfo Lima wrote:
> Hi, is there a reason why the compiler cannot deduce an array type
> along with its size during template function argument deduction?
> 
> For instance:
> 
> template <class T, int N> void test(T a[N]) {}
> 
> int a[10];
> test(a); // test isn't in the overload set, but should (IMHO)
> 
> This might be useful to avoid array -> pointer automatic conversion
> during function calls.
> 
> Regards,
> Rodolfo Lima.
> 

Because the parameter a decays to a pointer.

Make it a reference to an array.

template <class T, int N> void test(T (&a)[N]);

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply red 1/25/2009 3:06:07 AM


Rodolfo Lima wrote:

> Hi, is there a reason why the compiler cannot deduce an array type
> along with its size during template function argument deduction?
> 
> For instance:
> 
> template <class T, int N> void test(T a[N]) {}

This is exactly equivalent to
 template <class T, int N> void test(T a[]) {}
and
 template <class T, int N> void test(T *a) {}

The dimension of an array parameter in a function declaration is nothing
more than a comment. The compiler does not do anything with it, and
therefor also can't deduce the N in your template.

> 
> int a[10];
> test(a); // test isn't in the overload set, but should (IMHO)
> 
> This might be useful to avoid array -> pointer automatic conversion
> during function calls.

To avoid the array->pointer conversion, you must use a reference to an
array:
 template <class T, int N> void test(T (&a)[N]) {}

> 
> Regards,
> Rodolfo Lima.
> 
Bart v Ingen Schenau
-- 
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Bart 1/25/2009 12:28:29 PM

On 25 jan, 07:06, red floyd <no.spam.h...@example.com> wrote:
> Because the parameter a decays to a pointer.

Yes, but during argument type deduction (made in caller scope,
methinks), the parameter is still an array. It becomes a pointer to
code inside the function. I'm no compiler expert, but I think the
compiler has enough context to deduce the template type and size
correctly, so why it's not allowed to do so?

> Make it a reference to an array.
> template <class T, int N> void test(T (&a)[N]);

Thanks, it works. But the fact that you can do this trick just
confirms my previous statement about the compiler having the context
to do the correct deduction. Why resort to tricks when the
straightforward solution is attainable and preferred?

Regards,
rod

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Rodolfo 1/25/2009 12:33:44 PM

Rodolfo Lima wrote:
> Hi, is there a reason why the compiler cannot deduce an array type
> along with its size during template function argument deduction?
> 
> For instance:
> 
> template <class T, int N> void test(T a[N]) {}
> 
> int a[10];
> test(a); // test isn't in the overload set, but should (IMHO)
> 
> This might be useful to avoid array -> pointer automatic conversion
> during function calls.

Not that knowing size will help you any. This compiles just fine:

void test(int a[10])
{
     a[7] = 1;
}

int a[5];

test(a);


Also, even size information for fixed size arrays seems to be lost when 
passed into a function.

Try this:

void test1(int a[10])
{
     std::cout << sizeof(a)/sizeof(int) << std::endl;
}

int a[10];

std::cout << sizeof(a)/sizeof(int) << std::endl; // <-- 10
test1(a); // <-- 1

So it is essentially converted to a pointer as soon as you pass it in 
anywhere. I guess compiler only knows size of that particular instance 
of "a".

This

template <int N, class T> test(T a[])
{
    int size = N/sizeof(T);
}

int a[10];
test<sizeof(a)>(a);

will work as long as you pass in the same instance you originally 
defined. But you still can't forbid "a" from being anything other that 
fixed array, and it does look confusing -- users might think array size 
in elements is expected, instead of in bytes...

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Eugene 1/25/2009 12:49:11 PM

Eugene Zolenko wrote:
> So it is essentially converted to a pointer as soon as you pass it in

They way to do what you want is to use array references.
This prevents the array-to-pointer conversion from occurring.

     template <class T, int N> void test(T (&a)[N]);

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Hyman 1/26/2009 4:56:01 PM

On Jan 25, 6:33 pm, Rodolfo Lima <rodo...@rodsoft.org> wrote:
> On 25 jan, 07:06, red floyd <no.spam.h...@example.com> wrote:
>
> > Because the parameter a decays to a pointer.
>
> Yes, but during argument type deduction (made in caller scope,
> methinks), the parameter is still an array. It becomes a pointer to
> code inside the function. I'm no compiler expert, but I think the
> compiler has enough context to deduce the template type and size
> correctly, so why it's not allowed to do so?

Because you didn't declare a function taking an array parameter.  It
may /look/ like an array parameter, but (for compatability with C)
your function parameter a is of type "pointer to T".

> > Make it a reference to an array.
> > template <class T, int N> void test(T (&a)[N]);
>
> Thanks, it works. But the fact that you can do this trick just
> confirms my previous statement about the compiler having the context
> to do the correct deduction. Why resort to tricks when the
> straightforward solution is attainable and preferred?


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Martin 1/26/2009 4:58:20 PM

On Jan 25, 10:33 am, Rodolfo Lima <rodo...@rodsoft.org> wrote:
> On 25 jan, 07:06, red floyd <no.spam.h...@example.com> wrote:
>
> > Because the parameter a decays to a pointer.
>
> Yes, but during argument type deduction (made in caller scope,
> methinks), the parameter is still an array. It becomes a pointer to
> code inside the function.

Not quite. The adjustment of array type to pointer type happens at the
point of function declaration already (8.3.5[dcl.fct]/3). So when you
write this:

   void foo(int a[3]);

you have actually declared the function as:

   void foo(int* a);

By the time you call it, the only overload that participates in the
resolution is the one above, with the pointer argument. In your case,
that "int N" template argument is effectively not used in your
function declaration at all after the adjustment, which is why it's
not deduced. There's simply nothing to deduce at the point of the
call.



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Pavel 1/27/2009 12:26:47 AM

7 Replies
142 Views

(page loaded in 0.107 seconds)

Similiar Articles:













7/26/2012 6:38:34 AM


Reply: