Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pass reference to array in C++

Tags:

c++

Can any one help me understand the following code

#include <iostream>  void foo(const char * c) {    std::cout << "const char *" << std::endl; }  template <size_t N> void foo(const char (&t) [N]) {    std::cout << "array ref" << std::endl;    std::cout << sizeof(t) << std::endl; }  int main() {     const char t[34] = {'1'};     foo(t);      char d[34] = {'1'};     foo(d); } 

The output is

const char * array ref 34 

Why does the first foo calls the const char * version ? How can I make it call the reference version ?

like image 496
user511274 Avatar asked Mar 02 '11 21:03

user511274


People also ask

Can you pass an array by reference in C?

Passing arrays to functions in C/C++ are passed by reference. Even though we do not create a reference variable, the compiler passes the pointer to the array, making the original array available for the called function's use. Thus, if the function modifies the array, it will be reflected back to the original array.

How arrays are passed to functions in C?

To pass an entire array to a function, only the name of the array is passed as an argument. result = calculateSum(num); However, notice the use of [] in the function definition. This informs the compiler that you are passing a one-dimensional array to the function.

Can you pass arrays by reference?

The only reason for passing an array explicitly by reference is so that you can change the pointer to point to a different array. If a function only looks at the contents of an array, and does not change what is in the array, you usually indicates that by adding const to the parameter.

What is array in C How can you reference it?

Arrays are used to store multiple values in a single variable, instead of declaring separate variables for each value. To create an array, define the data type (like int ) and specify the name of the array followed by square brackets [].


2 Answers

Conversion of const char[N] to const char* is considered an "exact match" (to make literals easier, mainly), and between two exact matches a non-template function takes precedence.

You can use enable_if and is_array to force it to do what you want.


A messy way to force it might be:

#include <iostream>  template <typename T> void foo(const T* c) {    std::cout << "const T*" << std::endl; }  template <typename T, size_t N> void foo(const T (&t) [N]) {    std::cout << "array ref" << std::endl; }  int main() {     const char t[34] = {'1'};     foo(t);      char d[34] = {'1'};     foo(d); }  /* array ref array ref */ 

I realise that the OP had char not some generic T, but nonetheless this demonstrates that the problem lay in one overload being a template and not the other.

like image 158
Lightness Races in Orbit Avatar answered Sep 23 '22 16:09

Lightness Races in Orbit


Let's look at this modified example with no template.

void foo(const char * c) {     std::cout << "const char *" << std::endl; }  void foo(const char (&t) [34]) {     std::cout << "const char (&) [34]" << std::endl; }  int main() {     const char t[34] = {'1'};     foo(t); } 

My compiler says call of overloaded foo is ambiguous. This is because conversions from array to pointer are considered an "Exact" conversion sequence and are not better than the null conversion sequence for overload resolution (Standard section 13.3.3.1.1.)

In the original code, the template parameter N can be deduced as 34, but then both non-template foo(const char*) and foo<34>(const char (&)[34]) are considered in overload resolution. Since neither is better than the other by conversion rules, the non-template function beats the template function.

Fixing things seems tricky. It seems like the is_array template from header <type_traits> (from C++0x if possible or Boost if not) might help.

like image 25
aschepler Avatar answered Sep 23 '22 16:09

aschepler