javaLover
javaLover

Reputation: 6425

recognize all T of all calling function1<T> at compile time then add line function2<T>()

Is it possible to recognize all calling of a certain function in everywhere

function1<T1>(); function1<T4>(); ...

then add a line that calling this following line in a certain place?

function2<T1>(); function2<T4>(); ...

For example,

class X{
    template <class T> function1(){ }
    template <class T> function2(){ }
}

class A{}
class B{}
class C{}
int main(){
    X x;  

    //vvvv  this code (hopefully) will be auto generated (by macro?)
    x.function2<A>();
    x.function2<B>();    //<--- I don't care about order of A or B
    //x.function2<C>();  //<--- this line should not be generated
    //^^^^  Only X's function1 should be recognized,
    //             not other class's functions with the same name.

    x.function1<B>();  
    x.function1<A>();
    x.function1<B>(); ....  // called in various places in many .cpp
    //If it is called in another .cpp, but not here, it should still be recognized
}

Edit

My old code call :-

function2<T>() inside function1<T>()    

It costs CPU significantly (I profiled), because function1 have to check whether function2 was called or not every time.

Upvotes: 1

Views: 74

Answers (1)

Leon
Leon

Reputation: 32504

Here is a draft of a near-zero overhead solution that will work only if you are not going to invoke function1() before main():

#include <iostream>
#include <typeinfo>

template <class T>
void function2()
{
    std::cout << "function2<" << typeid(T).name() << ">()" << std::endl;
}

bool dummy = true;

template <class T>
struct Func1WasInstantiated
{
    struct CallFunc2
    {
        CallFunc2() { function2<T>(); }
        void operator()() const { dummy = false; }
    };

    static CallFunc2 callFunc2;
};

template <class T>
typename Func1WasInstantiated<T>::CallFunc2 Func1WasInstantiated<T>::callFunc2;

template <class T>
void function1()
{
    Func1WasInstantiated<T>::callFunc2();
    std::cout << "function1<" << typeid(T).name() << ">()" << std::endl;
}

int main()
{
    std::cout << "------- Entered main() ---------" << std::endl;
    function1<int>();
    function1<double>();
    function1<int>();
    return 0;
}

Output (check it on IDEONE):

function2<i>()
function2<d>()
------- Entered main() ---------
function1<i>()
function1<d>()
function1<i>()

The global variable dummy is the acceptor of the side effect, that ensures that Func1WasInstantiated<T>::callFunc2 is linked into the program and makes the code work as intended. Without the side effect contained in callFunc2() I can imagine an aggressively optimizing compiler eliminating that line from function1() (that is normal) and letting the linker leave out the callFunc2 objects as they become unreferenced (I cannot judge whether this would be against the C++ standard or not).

Upvotes: 1

Related Questions