Cara menyampaikan referensi ke argumen nama ketik templat

16

Apakah ada cara untuk melewatkan referensi sebagai argumen ke argumen tipe nama template? Maksud saya, alih-alih meneruskan int, misalnya, untuk meneruskan referensi ke 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
}

Saya tahu saya dapat membuat anggota 'ptr' menjadi referensi ke sebuah pointer dengan membuatnya T & di kelas, tapi saya bertanya-tanya apakah ini dapat dilakukan dari argumen yang dilewatkan ke argumen template.

Ikan zebra
sumber
Saya kira Anda ingin tetap dengan decltype, karena mengambil judul secara harfiah Anda hanya dapat menulisFoo<int*&>
idclev 463035818

Jawaban:

19

Anda sedang mencari Foo<decltype(a) &> foo1(a).

Alternatif yang lebih tidak jelas (yang berfungsi dalam kasus khusus ini) adalah Foo<decltype((a))> foo1(a).

HolyBlackCat
sumber
1
Ah itu masuk akal, terima kasih. Bagaimana cara kerja tanda kurung ganda di decltype ((a))? Bagaimana itu menjadikannya referensi?
Zebrafish
2
@Zebrafish Pada dasarnya, decltypebekerja secara berbeda tergantung pada apakah Anda memberinya nama variabel atau sesuatu yang lain (ekspresi sewenang-wenang). decltype(a)mengembalikan tipe variabel a(karena Anda hanya memberinya nama variabel). decltype((a)), di sisi lain, memberi Anda jenis ekspresi (a) (yang juga int), dengan referensi tambahan yang menunjukkan kategori nilai ekspresi. [1/2]
HolyBlackCat
(a)(dan juga a) adalah nilai, yang ditunjukkan oleh &(nilai x diwakili oleh &&, nilai tidak mengubah tipe sama sekali). Karena ekspresi tidak pernah memiliki tipe referensi, fakta yang decltypedapat menambahkan referensi ke tipe tidak dapat menyebabkan konflik. [2/2]
HolyBlackCat
3

Sebagai alternatif dari jawaban sebelumnya, Anda dapat menggunakan std :: reference_wrapper

std :: reference_wrapper adalah templat kelas yang membungkus referensi dalam objek yang dapat disalin dan dapat ditugaskan. Ini sering digunakan sebagai mekanisme untuk menyimpan referensi di dalam wadah standar (seperti std :: vector) yang biasanya tidak dapat menyimpan referensi.

#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));
}
Picaud Vincent
sumber