SFINAE mit friend class [Erledigt]



  • Hallo,

    ich will mit SFINAE überprüfen, ob eine Klasse eine gewisse Methode hat.
    Mein Problem ist, dass das nur funktioniert, wenn die Methode public ist. Wenn sie private ist, dann geht das nicht, obwohl die Klasse, die das überprüft eine Friend-Klasse ist.
    Mache ich etwas falsch oder geht das tatsächlich nicht?

    Hier mein Code:

    #include <iostream>
    #include <type_traits>
    
    /// Check if service supports config storage
    template <typename Service>
    std::true_type supportsConfigStorage_(decltype(&Service::setConfigStorage));
    
    template <typename Service>
    std::false_type supportsConfigStorage_(...);
    
    template <typename Service>
    constexpr bool supportsConfigStorage = decltype(supportsConfigStorage_<Service>(nullptr))::value;
    
    class Checker;
    
    struct Foo {
        void setConfigStorage() {}
    };
    
    struct Bar {
    private:
        friend class Checker;
        void setConfigStorage() {}
    };
    
    struct Checker
    {
        template<typename T>
        void print()
        {
            if constexpr (supportsConfigStorage<T>)
            {
               std::cout<<"Has config storage" << std::endl;
            }
            else
            {
               std::cout<<"Has NO config storage" << std::endl; 
            }
        }
    };
    
    int main()
    {
        Checker checker;
        checker.print<Foo>(); // "Has config storage"
        checker.print<Bar>(); // "Has NO config storage"
    
        return 0;
    }
    

    Hier kann man rumspielen.

    Danke im Voraus!

    Steffo


  • Mod

    Es ist ja nicht Checker, das die "Prüfung" unternimmt, sondern supportsConfigStorage_. Das Freundschaftverhältnis zu Checker ist daher unerheblich für den Wert von supportsConfigStorage_. Wenn du supportsConfigStorage_ zum Friend machst, bekommst du tatsächlich "Has config storage". Aber das sagt dir dann wieder nichts darüber, ob setConfigStorage für Checker sichtbar ist - das Ergebnis ist das gleiche ob mit oder ohne Zeile 22.

    PS: Da die template-friend-Deklaration nicht so offensichtlich ist, sie sollte lauten:

    struct Bar {
    private:
        // friend class Checker;  // Ist jetzt egal ob friend oder nicht
        template<class Service> friend std::true_type supportsConfigStorage_(decltype(&Service::setConfigStorage));
        void setConfigStorage() {}
    };
    


  • @SeppJ Oha! Das hat mir weitergeholfen! Ich hatte da einen Denkfehler, da im Produktiv-Code der Checker auch die setConfigStorage()-Methode aufruft und da brauchte ich auf jeden Fall den Checker als Friend-Class, aber in dem Fall auch zusätzlich die Template-Methode, da sie ja die Überprüfung macht!

    Danke!!! 🙂


Anmelden zum Antworten