Silinmiş bir işlev dolaylı olarak satıriçi
(Mevcut cevaplara ek)
... Ve silinen bir işlev, işlevin ilk bildirimi olacaktır (işlev şablonlarının açık uzmanlıklarını silmek dışında - silme, uzmanlığın ilk bildiriminde olmalıdır), yani bir işlevi bildiremez ve daha sonra silemezsiniz, bir çeviri birimine yerel olarak tanımlanır.
Alıntı yapma [dcl.fct.def.delete] / 4 :
Silinen bir işlev dolaylı olarak satır içi. ( Not: Tek tanım kuralı ( [basic.def.odr] ) silinmiş tanımlara uygulanır. - son not ] Bir işlevin silinmiş tanımı, işlevin ilk bildirimi veya bir işlev şablonunun açıkça uzmanlaşması için , bu uzmanlığın ilk beyanı. [Örnek:
struct sometype {
sometype();
};
sometype::sometype() = delete; // ill-formed; not first declaration
- son örnek )
Silinmiş bir tanım içeren birincil işlev şablonu özelleştirilebilir
Genel bir kural olsa da , uzmanlıklar aşırı yük çözünürlüğünün ilk adımına katılmadığı için işlev şablonlarını uzmanlaşmaktan kaçınmak olsa da, yararlı olabileceği bazı bağlamlar vardır. Örneğin, aşırı yüklenmemiş örtük olarak başka bir dönüşümle aşırı yüklemeye dönüştürülmesini istemeyecek tüm türleri eşleştirmek için hiçbir tanımı birincil işlev şablonu kullanıldığında; örn., tanımlanmamış, aşırı yüklenmemiş birincil işlev şablonunun açık uzmanlaşmasında kesin tür eşleşmeleri uygulayarak bir dizi örtük dönüşüm eşleşmesini örtük olarak kaldırmak.
C ++ 11'in silinen işlev kavramından önce, yalnızca birincil işlev şablonunun tanımını atlayarak bunu yapabilirdi, ancak bu , birincil işlev şablonunun yazarından hiçbir anlamsal niyet sağlamayan belirsiz tanımlanmamış referans hataları verdi (kasıtlı olarak atlandı) ?). Bunun yerine birincil işlev şablonunu açıkça silersek, uygun bir özel uzmanlığın bulunmaması durumunda hata iletileri çok daha hoş hale gelir ve ayrıca birincil işlev şablonunun tanımının ihmal / silinmesinin kasıtlı olduğunu gösterir.
#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< ...
}
Bununla birlikte, yukarıdaki birincil işlev şablonu için bir tanımı atlamak yerine, açık bir uzmanlaşma eşleşmediğinde belirsiz, tanımsız bir referans hatası vermek yerine, birincil şablon tanımı silinebilir:
#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; */
}
Silme amacının da açıkça görülebileceği daha okunabilir bir hata mesajı verir (burada tanımlanmamış bir referans hatası, geliştiricinin bunu düşünülmeyen bir hata olarak düşünmesine neden olabilir).
Neden bu tekniği kullanmak isteyelim ki? Yine, açık uzmanlıklar örtük dönüşümleri dolaylı olarak kaldırmak için yararlı olabilir .
#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; */
}