Funktionsaufruf mehrdeutig trotz = delete
-
Hallo
Was genau war die Überlegung des Standard-Komitees dahinter, folgenden Code mehrdeutig zu machen? War es nicht möglich, diesen Fehler mit der neuen
= delete
-Syntax zu unterbinden?struct A { A(int){} }; struct B { B(int) = delete; }; void f(A){} void f(B){} int main() { f(42); }
LG
-
Der Sinn hinter
delete
besteht darin, eine Fall darzulegen, der ausdrücklich untersagt werden soll. D.h., wenn ein Funktionsname mit entsprechenden Argumenten aufgerufen wird, soll dies diagnostiziert werden.Wenn "gelöschte" Funktionen in der overload resolution nicht berücksichtigt würden, welchen Zweck hätten sie dann? Dokumentation?
Edit: Zugegeben, dein Fall ist etwas spezieller als das. Aber die Regeln zu verkomplizieren ist auch ein Fehler. Z.T. müssen Regeln auf Kosten gewisser Szenarien simpel gehalten werden.
-
Du hast recht, da habe ich wohl nicht ganz verstanden, wie
=delete
funktioniert.
In meinem Fall hatB
einen Konstruktor in der Form vonB(char const*)
, was zu einer Mehrdeutigkeit führte, wenn ichf(0)
schreibe, weil ja das 0-Literal implizit in Zeiger konvertiert werden kann. Da dachte ich fälschlicherweise, dassB(int)=delete
Abhilfe verschafft.LG
-
Wenn du B(int) weglässt, gibts doch keine Überladungsmbiguitäten.
Abgesehen davon gibt es nullptr.
-
Was ist mit
explicit B(const char*);
?
-
Techel schrieb:
Wenn du B(int) weglässt, gibts doch keine Überladungsmbiguitäten.
Fytch schrieb:
weil ja das 0-Literal implizit in Zeiger konvertiert werden kann
http://coliru.stacked-crooked.com/a/218e19df2ef6ce56
Techel schrieb:
Abgesehen davon gibt es nullptr.
nullptr
hilft mir explizit B zu konstruieren, aber ich will mit 0 ja genau A konstruieren. Überall(int)0
statt 0 zu schreiben funktioniert, aber das ist in meinen Augen keine gute Lösung.
-
@Skylac06: Jo,
explicit
löst das Problem natürlich, will ich aber nicht machen, weil es Sinn macht,char const*
implizit in B zu konvertieren.Meine aktuelle Lösung ist es, eine Forwarding-Schicht für f zu benutzen, damit 0 korrekt mit
int
deduziert wird:struct A { A(int){} }; struct B { B(char const*){} }; void f(A){} void f(B){} template<typename T> void g(T&& x) { f(std::forward<T>(x)); } int main() { g(0); }
-
Andere Möglichkeit:
#include <type_traits> #include <utility> struct A { A(int){} }; struct B { template <typename T, typename std::enable_if_t<std::is_convertible_v<T, char const*>, int> = 0> B(T&& v) : B(static_cast<char const*>(std::forward<T>(v))){} explicit B(char const*){} }; void f(A){} void f(B){} int main() { f(0); f(nullptr); }