#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(); } // "[ ]" then "[ 2 ]" in gcc/icc