Try this
#include <iostream>
#include <deque>
// Really want to build this list before main() started!
struct ProfilePoint;
static std::deque<ProfilePoint *> pps;
// Costly construction, but only ever with literal/constexpr params.
// Templating, etc., also discourages non-local building in reality.
struct ProfilePoint {
ProfilePoint(int id, char const *i) : id_(id), inf_(i) { pps.push_back(this); }
void doStuff() { /* ... */ }
int id_;
char const *const inf_;
};
template<class IdDescription>
struct ProfilePoint_{
static ProfilePoint p;
};
template<class IdDescription>
ProfilePoint ProfilePoint_<IdDescription>::p( IdDescription::id(), IdDescription::description() );
#define PROFILE_POINT(theid,thedescription) \
struct ppdef_static_class{ \
static int id(){ return theid; } \
static const char* description(){ return thedescription; } \
};\
static ProfilePoint_<ppdef_static_class>
// Functions like this will be called concurrently in reality.
void bar(int cnt) {
for (int i = 0; i < cnt; ++i) {
// Dropping in a local definition/call should be enough to hook in to system
PROFILE_POINT(2, "description is a string literal") pp;
pp.p.doStuff();
/* ... */
}
}
void dump() {
std::cout << "[";
for (ProfilePoint *pp : pps) { std::cout << " " << pp->id_ << ":" << pp->inf_; }
std::cout << " ]" << std::endl;
}
int main() { dump(); bar(5); dump(); } // Does what you want
This works for MSVC 2013 and ideone http://ideone.com/Z3n1U0
This does require use of macro and to call doStuff() you have to do .p.doStuff(). You also cannot have more than 1 profile point in a function (but this can easily be fixed).
This works by defining a local class that is used as a parameter to a template class that has a static member. By referencing that template in the function, you force the compiler to instantiate the static member of the template.
Let me know if you have any questions about this technique.