Mengapa tidak perlu menggunakan nama samaran untuk jenis tergantung dalam kasus berikut?

10

Saya telah membaca tentang menghapus referensi jenis, di sini .

Ini memberi contoh berikut:

#include <iostream> // std::cout
#include <type_traits> // std::is_same

template<class T1, class T2>
void print_is_same() {
  std::cout << std::is_same<T1, T2>() << '\n';
}

int main() {
  std::cout << std::boolalpha;

  print_is_same<int, int>();
  print_is_same<int, int &>();
  print_is_same<int, int &&>();

  print_is_same<int, std::remove_reference<int>::type>(); // Why not typename std::remove_reference<int>::type ?
  print_is_same<int, std::remove_reference<int &>::type>();// Why not typename std::remove_reference<int &>::type ?
  print_is_same<int, std::remove_reference<int &&>::type>();// Why not typename std::remove_reference<int &&>::type ?
}

The types dalam std::remove_referencesifat-sifat yang jenis tergantung.

Kemungkinan implementasi

template< class T > struct remove_reference      {typedef T type;};
template< class T > struct remove_reference<T&>  {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};

Tapi mengapa itu tidak digunakan typename std::remove_reference</*TYPE*/>::type?

LernerCpp
sumber

Jawaban:

22

The types dalam std::remove_referencesifat-sifat yang jenis tergantung.

Tidak, mereka bukan nama yang tergantung di sini. Argumen templat telah ditentukan secara eksplisit sebagai int, int&dan int&&. Oleh karena itu, jenisnya diketahui pada saat ini.

Di sisi lain, jika Anda menggunakan std::remove_referencedengan parameter template, mis

template <typename T>
void foo() {
    print_is_same<int, typename std::remove_reference<T>::type>();
}

maka Anda harus menggunakan typenameuntuk memberi tahu bahwa itu std::remove_reference<T>::typeadalah tipe karena ekspresi Anda sekarang tergantung pada parameter template T.

songyuanyao
sumber
5

Singkatnya, Anda perlu typenamememastikan kompiler itu

std::remove_reference<int>::type

benar-benar tipe. Mari kita pertimbangkan beberapa templat lainnya

template <typename T>
struct foo {
    using type = int;
};

Berikut foo::typeini tipenya. Tetapi bagaimana jika seseorang memasok spesialisasi sepanjang garis

template <> struct foo<int> {
    int type;
};

Sekarang typebukan tipe tetapi sebuah int. Sekarang ketika Anda menggunakan foo di dalam templat:

template <typanem T> 
struct bar {
    using type = typename foo<T>::type;
};

Anda harus memastikan kompiler yang foo<T>::typebenar - benar tipe, bukan sesuatu yang lain, karena hanya melihat bar(dan templat utama foo) kompiler tidak dapat mengetahuinya.

Namun, dalam Anda mainyang std::remove_reference<int>::typetidak tergantung pada parameter template, maka compiler dapat mudah memeriksa apakah itu adalah tipe.

idclev 463035818
sumber
0

Kata kunci typename digunakan untuk bantuan compiler parse sumber. Ini menunjukkan id adalah nama jenis, bukan nama variabel atau nama metode. Tetapi dalam situasi seperti kompiler di atas dapat mengetahuinya sendiri, jadi kata kunci ini tidak diperlukan.

Sergey Strukov
sumber