คำถามที่น่าสนใจ เมื่อเร็ว ๆ นี้ฉันได้ดูการพูดคุยของแนวคิดของ Andrew Sutton และในช่วงถาม - ตอบมีคนถามคำถามต่อไปนี้ (เวลาประทับในลิงค์ต่อไปนี้):
CppCon 2018: Andrew Sutton "แนวคิดใน 60: ทุกสิ่งที่คุณจำเป็นต้องรู้
ดังนั้นคำถามเดือดลงไป: If I have a concept that says A && B && C, another says C && B && A, would those be equivalent?แอนดรูตอบว่าใช่ แต่ชี้ให้เห็นความจริงที่คอมไพเลอร์มีวิธีการบางอย่างภายใน (ที่มีความโปร่งใสให้กับผู้ใช้) ในการย่อยสลายแนวคิดเข้าไปในข้อเสนอตรรกะอะตอม ( atomic constraintsแอนดรูถ้อยคำระยะ) และการตรวจสอบไม่ว่าจะเป็น เท่ากัน
ตอนนี้ดูสิ่งที่ cppreference พูดเกี่ยวกับstd::same_as:
std::same_as<T, U>subsumes std::same_as<U, T>และในทางกลับกัน
มันเป็นพื้นสัมพันธ์ "if-and-only-if" พวกเขาหมายถึงกันและกัน (สมการเชิงตรรกะ)
การคาดเดาของฉันอยู่ที่นี่ จำกัด std::is_same_v<T, U>อะตอม วิธีที่คอมไพเลอร์ปฏิบัติstd::is_same_vอาจทำให้พวกเขาคิดstd::is_same_v<T, U>และstd::is_same_v<U, T>เป็นข้อ จำกัด ที่แตกต่างกันสองข้อ ดังนั้นหากคุณใช้งานstd::same_asโดยใช้หนึ่งในนั้น:
template< class T, class U >
concept same_as = detail::SameHelper<T, U>;
จากนั้นstd::same_as<T, U>และstd::same_as<U, T>จะ "ระเบิด" กับข้อ จำกัด ของอะตอมที่แตกต่างกันและจะไม่เทียบเท่ากัน
ทำไมคอมไพเลอร์จึงสนใจ?
ลองพิจารณาตัวอย่างนี้ :
#include <type_traits>
#include <iostream>
#include <concepts>
template< class T, class U >
concept SameHelper = std::is_same_v<T, U>;
template< class T, class U >
concept my_same_as = SameHelper<T, U>;
// template< class T, class U >
// concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;
template< class T, class U> requires my_same_as<U, T>
void foo(T a, U b) {
std::cout << "Not integral" << std::endl;
}
template< class T, class U> requires (my_same_as<T, U> && std::integral<T>)
void foo(T a, U b) {
std::cout << "Integral" << std::endl;
}
int main() {
foo(1, 2);
return 0;
}
จะเป็นการดีที่my_same_as<T, U> && std::integral<T>subsumes my_same_as<U, T>; ดังนั้นคอมไพเลอร์ควรเลือกแม่แบบเชี่ยวชาญสองยกเว้น ... มันไม่ได้: error: call of overloaded 'foo(int, int)' is ambiguousคอมไพเลอร์จะส่งเสียงข้อผิดพลาด
เหตุผลที่อยู่เบื้องหลังคือเนื่องจากmy_same_as<U, T>และmy_same_as<T, U>ไม่ได้รวมกันmy_same_as<T, U> && std::integral<T>และmy_same_as<U, T>กลายเป็นที่เปรียบมิได้
อย่างไรก็ตามหากคุณเปลี่ยน
template< class T, class U >
concept my_same_as = SameHelper<T, U>;
กับ
template< class T, class U >
concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;
รหัสรวบรวม
SameHelper<T, U>อาจเป็นจริงไม่ได้หมายความว่าSameHelper<U, T>อาจจะเป็น