Як передати посилання на аргумент типу шаблону


15

Чи є спосіб передати посилання як аргумент на аргумент типу імені шаблону? Я маю на увазі так, замість передачі int, наприклад, для передачі посилання на 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
}

Я знаю, що можу зробити член 'ptr' посиланням на покажчик, зробивши його T & у класі, але мені було цікаво, чи можна це зробити з аргументу, переданого аргументу шаблону.


Я припускаю, що ви хочете залишитися з цим decltype, адже взявши назву буквально, ви могли просто написатиFoo<int*&>
idclev 463035818

Відповіді:


18

Ви шукаєте Foo<decltype(a) &> foo1(a).

Більш незрозуміла альтернатива (яка працює в даному конкретному випадку) Foo<decltype((a))> foo1(a).


1
Ах, це має сенс, дякую. Як працюють подвійні дужки в decltype ((a))? Як це робить його посиланням?
Зебрафіш

2
@Zebrafish В основному, decltypeпрацює по-різному, залежно від того, чи дасте йому ім'я змінної чи щось інше (довільний вираз). decltype(a)повертає тип змінної a(тому що ви просто дали їй ім'я змінної). decltype((a)), з іншого боку, дає тип виразу (a) (який також є int), з доданою опорною приналежністю, яка вказує на категорію значення виразу. [1/2]
HolyBlackCat

(a)(як і a) - значення lvalue, яке позначається &(xvalues ​​представлені &&символом, prvalues ​​взагалі не змінюють тип). Оскільки вирази ніколи не мають посилальних типів, той факт, що decltypeможе додати посилання на тип, не може викликати конфліктів. [2/2]
HolyBlackCat

2

В якості альтернативи попередній відповіді можна використовувати std :: reference_wrapper

std :: reference_wrapper - шаблон класу, який обертає посилання в об'єкт, що може бути скопійований, який можна скопіювати. Він часто використовується як механізм для зберігання посилань всередині стандартних контейнерів (наприклад, std :: vector), які зазвичай не можуть містити посилання.

#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));
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.