Here's a clever/nasty hack using a technique described by Johannes Schaub - litb on his blog, Access to private members: Safer nastiness. All credit should go to Johannes. I'll take the blame for applying it to a real-world scenario (or maybe you can):
#include <windows.h>
#include <iostream>
#include "boost/thread.hpp"
using namespace std;
// technique for accessing private class members
//
// from: http://bloglitb.blogspot.com/2011/12/access-to-private-members-safer.html
//
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
struct thread_data_f {
typedef unsigned boost::detail::thread_data_base::*type;
friend type get(thread_data_f);
};
struct thread_id_f {
typedef boost::detail::thread_data_ptr boost::thread::id::*type;
friend type get(thread_id_f);
};
template struct Rob<thread_data_f, &boost::detail::thread_data_base::id>;
template struct Rob<thread_id_f, &boost::thread::id::thread_data>;
unsigned int get_native_thread_id( boost::thread const& t)
{
boost::detail::thread_data_ptr thread_data = t.get_id().*get(thread_id_f());
unsigned thread_id = (*thread_data).*get(thread_data_f());
return thread_id;
}
//
//
//
// test of get_native_thread_id()
void thread_func()
{
cout << "thread running..." << endl;
cout << "Windows says my ID is: " << GetCurrentThreadId() << endl;
for (;;) {
boost::this_thread::yield();
}
}
int main()
{
boost::thread t(thread_func);
::Sleep(2000);
cout << "boost says my thread ID is: " << get_native_thread_id(t) << endl;
return 0;
}
I'm not sure if this qualifies as a "good way" to get the info. But it works without modifying the boost headers or libraries, and the compiler doesn't complain at all - even with relatively high warnings. Tested on:
- MinGW 4.6.1
-Wall -Wextra
with a few especially noisy warnings turned off - but not for this test in particular. They're turned off in my generic 'compile this test' script.
- VC++ 2008 and 2010 with /W4
Here a sample run that shows it works:
C:\temp>test
thread running...
Windows says my ID is: 5388
boost says my thread ID is: 5388
Of course, it should go without saying that this might break if/when boost::thread changes over time, but probably not silently.
Some explanatory notes/pointers:
The 'loophole' used in this technique is in C++03 14.7.2/8 "Explicit instantiation":
The usual access checking rules do not apply to names used to specify
explicit instantiations. [Note: In particular, the template arguments
and names used in the function declarator (including parameter types,
return types and exception specifications) may be private types or
objects which would normally not be accessible and the template may be
a member template or member function which would not normally be
accessible.]
Dave Abrahams has a 'gist' that uses similar techniques along with comments that explain pretty nicely what's going on:
I found that in a comment he left on a previous article about private member access on Johannes' blog: Access to private members. That's easy!