เหตุใดจึงไม่จำเป็นต้องใช้ชื่อพิมพ์สำหรับประเภทที่อ้างอิงในกรณีต่อไปนี้


10

ผมได้อ่านเกี่ยวกับการลบการอ้างอิงจากประเภทที่นี่

มันให้ตัวอย่างต่อไปนี้:

#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 ?
}

types ในstd::remove_referenceลักษณะประเภทขึ้นอยู่กับ

การใช้งานที่เป็นไปได้

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;};

แต่ทำไมถึงไม่ใช้typename std::remove_reference</*TYPE*/>::type?

คำตอบ:


22

types ในstd::remove_referenceลักษณะประเภทขึ้นอยู่กับ

ไม่พวกเขาไม่ใช่ชื่อขึ้นอยู่กับที่นี่ ข้อโต้แย้งแม่แบบได้รับการระบุไว้อย่างชัดเจนว่าint, และint& int&&ดังนั้นประเภทเป็นที่รู้จักกัน ณ จุดนี้

ในทางกลับกันถ้าคุณใช้std::remove_referenceกับพารามิเตอร์แม่แบบเช่น

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

แล้วคุณจะต้องใช้typenameที่จะบอกว่าเป็นชนิดเป็นแสดงออกของคุณตอนนี้ขึ้นอยู่กับพารามิเตอร์แม่แบบstd::remove_reference<T>::typeT


5

สรุปคุณจะต้องtypenameแน่ใจว่าคอมไพเลอร์นั้น

std::remove_reference<int>::type

เป็นประเภทจริงๆ ให้พิจารณาเทมเพลตอื่น

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

นี่foo::typeคือประเภท แต่จะเกิดอะไรขึ้นถ้ามีคนจัดหาความเชี่ยวชาญให้กับพวกเขา

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

ตอนนี้typeไม่ได้เป็นประเภท intแต่ ตอนนี้เมื่อคุณใช้ foo ภายในเทมเพลต:

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

คุณต้องแน่ใจว่าคอมไพเลอร์foo<T>::typeเป็นประเภทไม่ใช่อย่างอื่นเพราะมองแค่bar(และเทมเพลตหลักfoo) คอมไพเลอร์ไม่สามารถรู้ได้

อย่างไรก็ตามในของคุณไม่ขึ้นอยู่กับพารามิเตอร์เทมเพลตจึงเรียบเรียงสามารถพร้อมตรวจสอบว่าเป็นชนิดmainstd::remove_reference<int>::type


0

คำหลักtypenameจะใช้ในการช่วยเหลือคอมไพเลอร์แจงแหล่งที่มา มันชี้ id เป็นชื่อประเภทไม่ใช่ชื่อตัวแปรหรือชื่อวิธีการ แต่ในสถานการณ์เช่นคอมไพเลอร์ด้านบนสามารถเข้าใจได้ด้วยตนเองดังนั้นคำหลักนี้จึงไม่จำเป็น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.