Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a reference to a template typename argument

Tags:

c++

templates

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.

like image 849
Zebrafish Avatar asked Mar 25 '20 13:03

Zebrafish


People also ask

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

Should I use typename or class in template?

For normal template parameters (neither template template parameters, or nor non-type template parameters), you can use either class or typename interchangeably, so these two mean exactly the same thing to the compiler: template <class foo> template <typename foo>

CAN default arguments be used with the template?

You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };

How do you use template arguments in C++?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)


2 Answers

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

like image 199
HolyBlackCat Avatar answered Oct 16 '22 00:10

HolyBlackCat


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));
}
like image 34
Picaud Vincent Avatar answered Oct 15 '22 23:10

Picaud Vincent