2 votes

Envelopper parfaitement une fonction

Je veux tracer tous mes appels OpenGL. À cette fin, j'ai la macro suivante :

#define EXEC_OPENGL(NAME, ARGUMENTS) debugOpengl(TOSTRING(NAME), [](void) { return NAME ARGUMENTS; })

EXEC_OPENGL(glDoSomething, (1, 2, 3, 4));

Et le debugOpengl Le code de la fonction est similaire à ceci :

void debugOpengl(char const * name, std::function<void ()> const & exec)
{
    GLenum err;

    exec();

    while((err = glGetError()) != GL_NO_ERROR) {
        std::cerr << "OpenGL Error: " << name << " " << err << std::endl;
    }
}

template <typename Ret>
Ret debugOpengl(char const * name, std::function<Ret ()> const & exec)
{
    GLenum err;

    auto ret = exec();

    while((err = glGetError()) != GL_NO_ERROR)
        std::cerr << "OpenGL Error: " << name << " " << err << std::endl;

    return ret;
}

Ce code ne fonctionne pas, car (au moins sur GCC 7) lorsqu'il s'agit de fonctions qui retournent void, la lambda définie dans la macro est invalide (car void value not ignored as it ought to be ).

J'ai également essayé d'écrire une classe de foncteur de modèle, mais cela a fini par être pénible et n'a pas fonctionné (mon transfert parfait n'a pas réussi à transférer correctement les nombres littéraux).

Quel est le bon moyen d'exécuter simplement quelque chose avant et après l'appel d'une fonction, en supposant que je puisse envelopper dans une macro tous les appels à cette fonction ?

1voto

Jarod42 Points 15729

Vous pouvez utiliser le RAII pour afficher les erreurs :

template <typename F>
class Finally {
public:
    Finally(F f) : f{f} {}
    Finally(const Finally&) = delete;
    Finally& operator=(const Finally&) = delete;

    ~Finally() noexcept {
        try {
            f();
        } catch (...) {
            std::cerr << "Exception during stack unwinding" << std::endl;
        }
    }
private:
    F f;
};

template <typename F>
decltype(auto) debugOpengl(const char* name, F&& f)
{
    Finally finally{[name](){
        GLenum err;
        while((err = glGetError()) != GL_NO_ERROR) {
        {
            std::cerr << "OpenGL Error: " << name << " " << err << std::endl;
        }
    }};
    return f();
}

Le code fourni utilise C++17, mais peut être réalisé en C++11.

0voto

Davis Herring Points 7254

C'est un bogue de GCC, depuis fixé : a le type de retour de lambda est déduit comme void s'il retourne une expression de ce type.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X