Wednesday, April 4, 2007

C++ Generic Programming: Sample of traits.


#include <windows.h>
#include <string>


//////////////////////////////////////////////////////////////////////////////


// Use of templates to call WIN32 API functions.


namespace win32 {


//////////////////////////////////////////////////////////////////////////////


template< class _Ch >
struct module_traits;


//////////////////////////////////////////////////////////////////////////////


class module {
typedef HMODULE _Myhandle;
public:
typedef _Myhandle handle_type;
typedef DWORD size_type;
static const size_type max_length = MAX_PATH;
module() :
m_handle(GetCurrentModule())
{ }
// No need to close module handles.
// TODO: check this assumption
~module()
{ }
// Using ::GetModuleFileName, obtain the full path name of m_handle.
template< class _Ch >
std::basic_string< _Ch >& get_filename(std::basic_string< _Ch >& _fn)
{
typedef module_traits< _Ch > _Tr;
_fn.resize(max_length);
size_type _n = _Tr::GetFileName(m_handle, &*_fn.begin(), max_length);
_fn.resize(_n);
return _fn;
}
// Using ::GetModuleFileName, obtain the full path name of m_handle.
template< class _Ch, class _AfxTr >
ATL::CStringT< _Ch, _AfxTr >&
get_filename(ATL::CStringT< _Ch, _AfxTr >& _fn)
{
typedef module_traits< _Ch > _Tr;
size_type _n = _Tr::GetFileName(m_handle, _fn.GetBuffer(max_length), max_length);
_fn.ReleaseBufferSetLength(_n);
return _fn;
}
// Using ::GetModuleFileName, obtain the full path name of m_handle.
template< class _Ch, size_t _Len >
size_type get_filename(_Ch (&_buff)[ _Len ])
{
typedef module_traits< _Ch > _Tr;
return _Tr::GetFileName(m_handle, _buff, _Len);
}
// Using ::GetModuleFileName, obtain the full path name of m_handle.
template< class _Ch >
size_type get_filename(_Ch* _buff, size_t _len)
{
typedef module_traits< _Ch > _Tr;
return _Tr::GetFileName(m_handle, _buff, _len);
}
private:
// TODO: implement this.
_Myhandle GetCurrentModule()
{ return NULL; }
_Myhandle m_handle;
};


//////////////////////////////////////////////////////////////////////////////


template< >
struct module_traits< char > {
static char space() { return ' '; }
static DWORD GetFileName(HMODULE _h, char* _buff, DWORD _size)
{ return ::GetModuleFileNameA(_h, _buff, _size); }
};


template< >
struct module_traits< wchar_t > {
static char space() { return L' '; }
static DWORD GetFileName(HMODULE _h, wchar_t* _buff, DWORD _size)
{ return ::GetModuleFileNameW(_h, _buff, _size); }
};


//////////////////////////////////////////////////////////////////////////////


}; // namespace win32



Client 1:




try {
// Get our module path and file name and save as m_self.
win32::module _self;
_self.get_filename(m_self);



// Locate our "home" directory and any other interesting places
// and tuck them away for later reference via GetApp().
int _slash = m_self.ReverseFind(_T('\\'));
if (_slash >= 0) {
m_bin = m_self.Left(_slash);
m_home = FindHome(m_bin);
} else {
m_bin = _T(".");
m_home = m_bin;
}




// This is our resource path.
m_res = m_home + _T("\\Resource");

// This is our help path.
m_help = m_home + _T("\\Help");
// Welcome dialog is entire application
//CWelcomeDlg welcomeDlg;
//m_pMainWnd = &welcomeDlg;
//welcomeDlg.DoModal();
m_pMainWnd = &m_WelcomeDlg;
m_WelcomeDlg.DoModal();




// Must not let MFC try to close this window!
m_pMainWnd = NULL;
}




catch (const std::exception& _ex) {
CString _what(_ex.what());
AfxMessageBox(_what);
}


Client 2:


// Provides standard stream output for CString.
template< class _Ch, class _Tr, class _AfxTr > inline
std::basic_ostream< _Ch, _Tr >&
operator<<(std::basic_ostream< _Ch, _Tr >& _out,
const ATL::CStringT< _Ch, _AfxTr >& _str)
{ return _out << static_cast<const _Ch*>(_str); }


int main(int _argc, char** _argv)
{
using namespace std;

win32::module _module;


std::string _filename;
_module.get_filename(_filename);
cout << "I am module: " << _filename << " -- hello, world!" << endl;


std::wstring _wfilename;
_module.get_filename(_wfilename);
wcout << L"I am module: " << _wfilename << L" -- hello, world!" << endl;


CStringA _cfilename;
_module.get_filename(_cfilename);
cout << "I am module: " << _cfilename << " -- hello, world!" << endl;


CStringW _cwfilename;
_module.get_filename(_cwfilename);
wcout << L"I am module: " << _cwfilename << L" -- hello, world!" << endl;


char _afilename[ 300 ];
_module.get_filename(_afilename);
cout << "I am module: " << _afilename << " -- hello, world!" << endl;


win32::GetModuleFileName(NULL, _afilename);
cout << "I am module: " << _afilename << " -- hello, world!" << endl;


return 0;
}


No comments: