Marco Agnese
Marco Agnese

Reputation: 369

Reference vs pointer specilization

Let's suppose that we have the following code:

template<class T>
void foo(T& v)
{
  std::cout<<v[0]<<std::endl;
}

template<class T>
void foo(T* v)
{
  std::cout<<v[0]<<std::endl;
}

void main(void)
{
  std::vector<int> vec(5,1);
  foo(vec);

  int* cvec(new int[5]);
  cvec[0]=1;
  foo(cvec);
}

is there a way to avoid rewriting the body of the second function, by simply calling the first function (maybe doing some kind of cast or something like that)?

UPDATE Maybe my main was a bit misleading but I want to call foo also with C-style array and not with a pointer to a std::vector.

Upvotes: 2

Views: 114

Answers (4)

I think you created a problem for yourself... if what you want is to have a template function foo that can operate on arrays you can just use the base template:

template <typename T>
void foo(T & t) {
   t[0];
}

int main() {
   int array[0] = { 123 };
   foo(array);
   std::vector<int> v{ 123 };
   foo(v);
}

The key here is that the deduced type for an argument of type array will be decayed to a pointer if the function argument is by value, but it won't decay if the argument is a reference.

Upvotes: 0

davidhigh
davidhigh

Reputation: 15478

As mentioned in the comments, you can also use the unspecified base template, if you further use a helper for the accessing the parameter:

#include <iostream>

template<typename T> T&& call(T&& t) {return std::forward<T>(t);}
template<typename T> T& call(T* t) {return *t;}

template<typename T>
void foo(T&& t)
{
    std::cout<<"foo: "<<call(std::forward<T>(t))<<std::endl;
}

template<typename T>
void bar(T&& t)
{
    std::cout<<"bar: "<<call(std::forward<T>(t))<<std::endl;
}

int main()
{
    int a=1;
    int *b=new int(2);

    foo(a);
    foo(b);
    foo(3);

    bar(a);
    bar(b);

    // your code goes here
    return 0;
}

As one can notice, this method is helpful as one doesn't need to specialize each class template anew, but always use the base template together with the once implemented call functions. foo, bar and any other function will work for pointers and (lvalue- and rvalue-) references at the same time.

Upvotes: 0

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

"is there a way to avoid rewriting the body of the second function, by simply calling the first function (maybe doing some kind of cast or something like that)?"

You can write

template<class T>
void foo(T& v) {
    foo(&v);
}

too pass the pointer to T&.
Or the other way round

template<class T>
void foo(T* v) {
    foo(*v);
}

by dereferencing the T*.

Upvotes: 1

Jared Wadsworth
Jared Wadsworth

Reputation: 847

consider the following code:

template<class T>
void foo(T& v)
{
    std::cout << v[0] << std::endl;
}

template<class T>
void bar(T* v)
{
    foo(*v);
}

void main(void)
{
    std::vector<int> vec(5,1);
    foo(vec);
    bar(&(vec[0]));
}

remember that pointers are merely variable which hold an address, so since foo requires an address its perfectly legal to simply pass it the pointer value, which is in fact an address.

Hope that helps!

Upvotes: 0

Related Questions