c++overridingcmath

What would be the best approach to override cmath functions while still using them?


I'm trying to make my own math library with support for keeping stats on how many times each mathematical function in used. I would like all functions to have the same name as those in cmath so that I can easily just replace my math library header with cmath in my code and have it work the same way, just without the stats.

So far I've tried this:

my_math.hpp

float tanf(float ang);

my_math.cpp

#include <cmath>

float tanf(float ang)
{
    std::cout << "Custom tanf() used..." << std::endl;

    return std::tan((float)(ang));
}

Is this the best approach or is there a better one?

I've tried to use return std::tanf(ang) but get the error that "tanf is not a member of std", even though I can use tanf in other parts of the code where I don't have my own tanf declared (I can never use std::tanf though).

Is there a way to do this so that I can declare my own functions with the same name as the ones in cmath, add some functionality and then use the cmath version in the return?


Solution

  • To expand on my comment, and presuming this is part of some test-framework type thing, this could work how you want?

    // my_math.hpp
    namespace jesper
    {
        float tanf(float ang);
        /* more functions declarations */
    }
    
    // my_math.cpp
    #include "my_math.hpp"
    float jesper::tanf(float ang)
    {
        /* function definition */
    }
    /* more function definitions */
    
    // my_test_code.cpp
    #include <cmath>
    #include "my_math.hpp"
    
    constexpr bool use_my_math = true; // switch this to change between std and jesper in helper functions
    
    float generic_tanf(float ang)
    {
        if constexpr (use_my_math)
            return jesper::tanf(ang);
        else
            return std::tanf(ang);
    }
    /* more helper functions */
    
    int main()
    {
        generic_tanf(0.1f);
    }
    

    This style would switch all your functions at compile time, you could also use other methods for compile time checks and re-organise things nicely. Or you could do things at runtime with similar helper functions.

    You could perhaps also do something more akin to what I think you are asking for using horrible using namepsace std type stuff, but this is usually advised against for the reason you're wanting it, and it would most likely go badly. Name collision is not usually desirable!