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


  • Mod

    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 hat B einen Konstruktor in der Form von B(char const*) , was zu einer Mehrdeutigkeit führte, wenn ich f(0) schreibe, weil ja das 0-Literal implizit in Zeiger konvertiert werden kann. Da dachte ich fälschlicherweise, dass B(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);
    }
    

  • Mod

    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);
    }
    

Anmelden zum Antworten