Eine gelöschte Funktion ist implizit inline
(Nachtrag zu bestehenden Antworten)
... Und eine gelöschte Funktion ist die erste Deklaration der Funktion (außer zum Löschen expliziter Spezialisierungen von Funktionsvorlagen - das Löschen sollte bei der ersten Deklaration der Spezialisierung erfolgen), dh Sie können eine Funktion nicht deklarieren und später beispielsweise löschen. bei seiner Definition lokal zu einer Übersetzungseinheit.
Zitieren von [dcl.fct.def.delete] / 4 :
Eine gelöschte Funktion ist implizit inline. ( Hinweis: Die Ein-Definition - Regel ( [basic.def.odr] ) gilt für gelöschte Definitionen -. Endnote ] Eine Definition einer Funktion gelöscht wird die erste Erklärung der Funktion oder für eine explizite Spezialisierung einer Funktionsvorlage sein , die erste Erklärung dieser Spezialisierung. [Beispiel:
struct sometype {
sometype();
};
sometype::sometype() = delete; // ill-formed; not first declaration
- Beispiel beenden )
Eine primäre Funktionsvorlage mit einer gelöschten Definition kann spezialisiert werden
Obwohl eine allgemeine Faustregel lautet , Spezialisierungsfunktionsvorlagen zu vermeiden, da Spezialisierungen nicht am ersten Schritt der Überlastungsauflösung teilnehmen, gibt es einige Kontexte, in denen dies nützlich sein kann. Beispiel: Wenn Sie eine nicht überladene primäre Funktionsvorlage ohne Definition verwenden, um allen Typen zu entsprechen, die nicht implizit in eine ansonsten durch Konvertierung übereinstimmende Überladung konvertiert werden sollen. dh implizite Entfernung einer Anzahl von impliziten Konvertierungsübereinstimmungen, indem nur exakte Typübereinstimmungen in der expliziten Spezialisierung der nicht definierten, nicht überladenen primären Funktionsvorlage implementiert werden.
Vor dem gelöschten Funktionskonzept von C ++ 11 konnte man dies tun, indem man einfach die Definition der primären Funktionsvorlage wegließ, aber dies ergab obskure undefinierte Referenzfehler , die dem Autor der primären Funktionsvorlage wohl keine semantische Absicht gaben (absichtlich weggelassen) ?). Wenn wir stattdessen die primäre Funktionsvorlage explizit löschen, werden die Fehlermeldungen, falls keine geeignete explizite Spezialisierung gefunden wird, viel schöner und zeigen auch, dass das Auslassen / Löschen der Definition der primären Funktionsvorlage beabsichtigt war.
#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< ...
}
Anstatt jedoch einfach eine Definition für die obige primäre Funktionsvorlage wegzulassen und einen obskuren undefinierten Referenzfehler zu erhalten, wenn keine explizite Spezialisierung übereinstimmt, kann die primäre Vorlagendefinition gelöscht werden:
#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; */
}
Es wird eine besser lesbare Fehlermeldung angezeigt, bei der auch die Löschabsicht deutlich sichtbar ist (bei der ein undefinierter Referenzfehler dazu führen kann, dass der Entwickler dies für einen unüberlegten Fehler hält).
Zurück zu dem Grund, warum wir diese Technik jemals anwenden wollen? Auch hier können explizite Spezialisierungen hilfreich sein, um implizite Konvertierungen implizit zu entfernen.
#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; */
}