ประเภทเทมเพลตและความกำกวมกลับอัตโนมัติ


20

ฉันมีฟังก์ชั่นเทมเพลตมากเกินไป:

template<typename T1, typename T2>
auto overMax(T1 a, T2 b)
{
    std::cout << __FUNCSIG__ << std::endl;

    return b < a ? a : b;
}

template<typename RT, typename T1, typename T2>
RT overMax(T1 a, T2 b)
{
    std::cout << __FUNCSIG__ << std::endl;

    return b < a ? a : b;
}

ถ้าฉันเรียกมันว่าสิ่งนี้:

auto a = overMax(4, 7.2); // uses first template
auto b = overMax<double>(4, 7.2); // uses second template

ทุกอย่างใช้งานได้ดี แต่

auto c = overMax<int>(4, 7.2); // error

ทำให้เกิดการโทรที่ไม่ชัดเจน

ทำไมถึงเป็นเช่นนั้นด้วยintและ OK เป็นประเภทอื่น


4
ผมคิดว่า ... .... วิธีคอมไพเลอร์เห็นมันคือกับintคุณจะระบุtypename RTหรือtypename T1? ตั้งแต่4ยังเป็นintมันอาจเป็นได้ทั้ง ด้วยdouble, 4ไม่ตรงกับประเภทโดยตรงdouble , ดังนั้นจึงควรใช้งานเกินพิกัดที่สอง
ChrisMM

สิ่งนี้ดูเหมือนว่าจะเป็นเรื่องเล็กน้อยสำหรับฉันเพราะคุณเป็นประเภทการรับคืนมากเกินไปในประเภทส่งคืน แต่ด้วยแม่แบบที่มีพารามิเตอร์ต่างกัน
Borgleader

คำตอบ:


25

RTไม่สามารถหักลดหย่อนได้ดังนั้นเมื่อไม่ให้บริการtemplate<typename T1, typename T2> auto overMax(T1 a, T2 b)สามารถเรียกได้เท่านั้น

เมื่อคุณ (บางส่วน) ระบุอาร์กิวเมนต์เทมเพลตหนึ่งวิธีทั้งสองจะใช้งานได้

แต่ขึ้นอยู่กับการโต้แย้งเราสามารถเป็นผู้สมัครที่ดีกว่า:

  • สำหรับ auto b = overMax<double>(4, 7.2); // uses second template

    ทั้งสองoverMax<double, int, double>และoverMax<double, double>มีศักยภาพ
    แต่overMax<double, int, double>เป็นการจับคู่ที่แน่นอน
    ในขณะที่overMax<double, double>ต้องมีintการdoubleแปลง

  • สำหรับ auto c = overMax<int>(4, 7.2); // Ambiguous call

    ทั้งสองoverMax<int, int, double>และoverMax<int, double>มีศักยภาพ
    แต่ไม่มีการจับคู่ที่ดีกว่าหรือมีความเชี่ยวชาญมากกว่าดังนั้นการโทรจึงไม่ชัดเจน


ทำไมถึงไม่ดีกว่ากันเลย ฉันถูกต้องหรือไม่ว่าในกรณีที่มีกำปั้นเกินพิกัด <int> (4, 7.2); จะทำให้เกิดการเปลี่ยนแปลงของ7.2เพื่อint และในกรณีที่สองผลลัพธ์ที่ส่งคืนซึ่งเริ่มต้นเป็นสองเท่าจะถูกแปลงเป็นintเนื่องจาก<int>ชัดเจนหรือไม่
เครื่องขยายเสียง

1
@amplifier: overMax<int>(4, 7.2)จะเป็นในกรณีแรกT1=int(ให้ไว้), T2=double(อนุมาน) และในกรณีที่สองRT=int(ระบุ), T1=int, T2=double(อนุมาน) คำจำกัดความของเนื้อหาของทั้งสองวิธีไม่ได้ใช้เพื่อเลือกการโอเวอร์โหลด
Jarod42

สำหรับฉันแล้วกรณีที่สองเหมาะสมเพราะมีการแปลงชนิดส่งคืนสำหรับกรณีแรกและไม่มีการแปลงเลยสำหรับวินาที
เครื่องขยายเสียง

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