คำถามที่น่าสนใจ เมื่อเร็ว ๆ นี้ฉันได้ดูการพูดคุยของแนวคิดของ 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>
อาจจะเป็น