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.


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


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));
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.