• [^] # Re: Allocs

    Posté par . En réponse au journal Une 20-aine de lignes de code pour le defer de Go en C++. Évalué à 7.

    Les lambdas "decay" en simple pointeur de fonction quand elles n'ont pas d'état. Je crois que la plupart du temps on souhaite que ces fonctions de nettoyage capturent tout par référence. Donc ça risque de pas être tip-top.

    Voilà ma tentative d'implémentation, il faut au minimum C++14, et ça nécessite simplement d'avoir accès à std::move.

    #include <utility>
    template<typename TCallback>
    class Defer {
    private:
     TCallback mCallback;
    public:
     Defer(TCallback&& callback)
     : mCallback(std::move(callback)) {}
     ~Defer() noexcept {
     mCallback();
     }
    };
    struct detail_defer_tag {};
    template <typename TCallback>
    auto operator+(const detail_defer_tag&, TCallback&& callback) {
     return Defer<TCallback>(std::move(callback));
    }
    #define CONCAT_IMPL( x, y ) x##y
    #define MACRO_CONCAT( x, y ) CONCAT_IMPL( x, y )
    #define defer const auto MACRO_CONCAT(d_, __COUNTER__) = detail_defer_tag{} + [&]()
    static volatile bool hasResource = false;
    int main(int argc, const char**) {
     int retVal = argc;
     hasResource = true;
     defer {
     hasResource = false;
     };
     if (hasResource) {
     retVal--;
     }
     return retVal;
    }

    Avec le lien godbolt qui va bien pour montrer que ça optimise pas trop mal: https://godbolt.org/z/7bK7q8Phe