Zebrafish
Zebrafish

Reputation: 13876

How to pass a reference to a template typename argument

Is there a way to pass a reference as an argument to a template typename argument? I mean so instead of passing an int, for example, to pass a reference to an int.

template <typename T>
struct Foo
{
    Foo(T arg) : ptr(arg) {}
    T ptr;
};

int main() 
{
    int* a = new int(6);
    Foo<decltype(a)> foo1(a); // ptr is a copy of a pointer
    Foo<decltype(&a)> foo1(&a); // ptr seems to be a pointer to a pointer
}

I know I can make the 'ptr' member be a reference to a pointer by making it T& in the class, but I was wondering if this can be done from argument that's passed to the template argument.

Upvotes: 16

Views: 2614

Answers (2)

Picaud Vincent
Picaud Vincent

Reputation: 10982

As an alternative to the previous answer, you can use std::reference_wrapper

std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.

#include <functional>

template <typename T>
struct Foo
{
  Foo(T arg) : ptr(arg)
  {
  }
  T ptr;
};

int main()
{
  int* a = new int(6);

  Foo<std::reference_wrapper<int*>> foo1(std::ref(a));
  foo1.ptr[0] = 1;  // ok

  // This also works
  int* b = new int(6);
  Foo<std::reference_wrapper<decltype(b)>> foo2(std::ref(b));
  // and this too
  foo1 = foo2;

  // Or, if you use c++17, even this
  Foo foo3(std::ref(b));
}

Upvotes: 3

HolyBlackCat
HolyBlackCat

Reputation: 96246

You're looking for Foo<decltype(a) &> foo1(a).

A more obscure alternative (which works in this specific case) is Foo<decltype((a))> foo1(a).

Upvotes: 19

Related Questions