ฟังก์ชั่นที่ถูกลบเป็นแบบอินไลน์โดยนัย
(ภาคผนวกของคำตอบที่มีอยู่)
... และฟังก์ชั่นที่ถูกลบจะเป็นการประกาศครั้งแรกของฟังก์ชั่น (ยกเว้นการลบความเชี่ยวชาญเฉพาะด้านของแม่แบบฟังก์ชั่น - การลบควรอยู่ที่การประกาศครั้งแรกของความเชี่ยวชาญ) ซึ่งหมายความว่าคุณไม่สามารถประกาศฟังก์ชั่น ที่ definition แบบโลคัลเป็นหน่วยการแปล
อ้างถึง[dcl.fct.def.delete] / 4 :
ฟังก์ชั่นที่ถูกลบเป็นแบบอินไลน์โดยนัย ( หมายเหตุ:กฎหนึ่งนิยาม ( [basic.def.odr] ) นำไปใช้กับคำจำกัดความที่ถูกลบ - หมายเหตุท้าย ] คำนิยามที่ถูกลบของฟังก์ชั่นจะเป็นการประกาศครั้งแรกของฟังก์ชั่นหรือสำหรับความเชี่ยวชาญเฉพาะของแม่แบบฟังก์ชั่น การประกาศครั้งแรกของความเชี่ยวชาญนั้น [ตัวอย่าง:
struct sometype {
sometype();
};
sometype::sometype() = delete; // ill-formed; not first declaration
- ตัวอย่างท้าย )
แม่แบบฟังก์ชั่นหลักที่มีความหมายที่ถูกลบสามารถเฉพาะ
แม้ว่ากฎทั่วไปของหัวแม่มือคือการหลีกเลี่ยงแม่แบบฟังก์ชั่นที่เชี่ยวชาญเป็นพิเศษไม่ได้มีส่วนร่วมในขั้นตอนแรกของการแก้ปัญหาเกินพิกัดที่มีเนื้อหาบางบริบทที่สามารถเป็นประโยชน์ เช่นเมื่อใช้เท็มเพลตฟังก์ชั่นหลักที่ไม่มีภาระมากเกินไปโดยไม่มีคำจำกัดความเพื่อจับคู่ทุกประเภทที่เราไม่ต้องการแปลงให้เป็นโอเวอร์โหลดที่ตรงกันโดยการแปลง กล่าวคือในการลบจำนวนของการจับคู่การแปลงโดยนัยโดยการใช้การจับคู่ประเภทที่แน่นอนเท่านั้นในการระบุเฉพาะอย่างชัดเจนของเท็มเพลตฟังก์ชันหลักที่ไม่ได้กำหนดไว้และไม่โอเวอร์โหลด
ก่อนที่แนวคิดเกี่ยวกับฟังก์ชันที่ถูกลบของ C ++ 11 เราสามารถทำได้โดยเพียงแค่ละเว้นคำจำกัดความของเท็มเพลตฟังก์ชันหลัก แต่สิ่งนี้ทำให้ข้อผิดพลาดการอ้างอิงที่ไม่ได้กำหนดชัดเจนซึ่งเนื้อหาไม่ได้ให้ความหมาย ?) หากเราลบเท็มเพลตฟังก์ชั่นหลักอย่างชัดเจนแทนข้อความแสดงข้อผิดพลาดในกรณีที่ไม่พบความเชี่ยวชาญเฉพาะทางที่เหมาะสมกลายเป็นดีกว่ามากและยังแสดงให้เห็นว่าการละเว้น / การลบคำจำกัดความของเทมเพลตฟังก์ชันหลักนั้น
#include <iostream>
#include <string>
template< typename T >
void use_only_explicit_specializations(T t);
template<>
void use_only_explicit_specializations<int>(int t) {
std::cout << "int: " << t;
}
int main()
{
const int num = 42;
const std::string str = "foo";
use_only_explicit_specializations(num); // int: 42
//use_only_explicit_specializations(str); // undefined reference to `void use_only_explicit_specializations< ...
}
อย่างไรก็ตามแทนที่จะละเว้นการนิยามสำหรับเท็มเพลตฟังก์ชันหลักด้านบนทำให้เกิดข้อผิดพลาดการอ้างอิงที่ไม่ชัดเจนซึ่งไม่ชัดเจนเมื่อไม่มีความเชี่ยวชาญที่ชัดเจนตรงกับนิยามเท็มเพลตหลักสามารถลบได้:
#include <iostream>
#include <string>
template< typename T >
void use_only_explicit_specializations(T t) = delete;
template<>
void use_only_explicit_specializations<int>(int t) {
std::cout << "int: " << t;
}
int main()
{
const int num = 42;
const std::string str = "foo";
use_only_explicit_specializations(num); // int: 42
use_only_explicit_specializations(str);
/* error: call to deleted function 'use_only_explicit_specializations'
note: candidate function [with T = std::__1::basic_string<char>] has
been explicitly deleted
void use_only_explicit_specializations(T t) = delete; */
}
ผลผลิตข้อความเพิ่มเติมอ่านได้มากขึ้นข้อผิดพลาดที่เจตนาการลบยังสามารถมองเห็นได้อย่างชัดเจน (ในกรณีที่การอ้างอิงที่ไม่ได้กำหนดข้อผิดพลาดที่อาจนำไปสู่การพัฒนาที่คิดนี้ผิดพลาด unthoughtful)
กลับไปที่สาเหตุที่เราเคยต้องการใช้เทคนิคนี้หรือไม่ อีกครั้งเฉพาะด้านอย่างชัดเจนอาจจะมีประโยชน์ในการปริยายลบแปลงโดยปริยาย
#include <cstdint>
#include <iostream>
void warning_at_best(int8_t num) {
std::cout << "I better use -Werror and -pedantic... " << +num << "\n";
}
template< typename T >
void only_for_signed(T t) = delete;
template<>
void only_for_signed<int8_t>(int8_t t) {
std::cout << "UB safe! 1 byte, " << +t << "\n";
}
template<>
void only_for_signed<int16_t>(int16_t t) {
std::cout << "UB safe! 2 bytes, " << +t << "\n";
}
int main()
{
const int8_t a = 42;
const uint8_t b = 255U;
const int16_t c = 255;
const float d = 200.F;
warning_at_best(a); // 42
warning_at_best(b); // implementation-defined behaviour, no diagnostic required
warning_at_best(c); // narrowing, -Wconstant-conversion warning
warning_at_best(d); // undefined behaviour!
only_for_signed(a);
only_for_signed(c);
//only_for_signed(b);
/* error: call to deleted function 'only_for_signed'
note: candidate function [with T = unsigned char]
has been explicitly deleted
void only_for_signed(T t) = delete; */
//only_for_signed(d);
/* error: call to deleted function 'only_for_signed'
note: candidate function [with T = float]
has been explicitly deleted
void only_for_signed(T t) = delete; */
}