I am trying to expand my template programming skills and I am facing a problem to which I don’t see the right solution for.
This is a personal training execise only to do some more advanced templating.
This the goal : write a template to convert any integer type (using sprintf or swprintf) to either string or wstring depending on the type of the format sring.
There is no need for error-checking (for now anuway).
The problem is when an format is specified as (const char*) NULL or (const wchar_t*) NULL
I need to supply a default LITERAL value as either "%i" or L"%i"
an for that I need to determine the char-type of the format-variable.
I am using a functions for that now ,using SFINAE.
However I would like to use a variable for that ,but I don’t think SFINAY works on varaiables (or am i wrong).
Here is my (working) code so far:
////////////////////////////////////////////////////////////////////////////////
template < typename T ,typename I >
inline
typename std::enable_if< std::is_same< T ,char >::value ,int >::type
str_printf ( T* szBuff ,int iLen ,const T* szFrmt ,I iNum )
{ return sprintf_s( szBuff ,iLen ,szFrmt ,iNum ); }
template < typename T ,typename I >
inline
typename std::enable_if< std::is_same< T ,wchar_t >::value ,int >::type
str_printf ( T* szBuff ,int iLen ,const T* szFrmt ,I iNum )
{ return swprintf_s( szBuff ,iLen ,szFrmt ,iNum ); }
////////////////////////////////////////////////////////////////////////////////
template < typename T >
inline
typename std::enable_if< std::is_same< T ,char >::value ,const char* >::type
Dflt_Frmt () { return "%i"; }
template < typename T >
inline
typename std::enable_if< std::is_same< T ,wchar_t >::value ,const wchar_t* >::type
Dflt_Frmt () { return L"%i"; }
////////////////////////////////////////////////////////////////////////////////
template < typename T ,typename I >
inline
std::basic_string< T ,std::char_traits < T > >
to_string ( I iNum ,const T* pszFrmt )
{
const int iLen (65);
T szBuff [iLen] = {0};
std::basic_string< T ,std::char_traits < T > > frmt ((pszFrmt && (*pszFrmt)) ? pszFrmt : Dflt_Frmt<T>() );
str_printf( szBuff ,iLen ,frmt.c_str() ,iNum );
return szBuff;
}
////////////////////////////////////////////////////////////////////////////////
this this what i would like to do (obviously it’s not workin)
////////////////////////////////////////////////////////////////////////////////
template < typename T ,typename I >
inline
std::basic_string< T ,std::char_traits < T > >
to_string ( I iNum ,const T* pszFrmt )
{
const int iLen (65);
T szBuff [iLen] = {0};
// declare a Variable of const T* and initialie it with "%i" or L"%i"
typename std::enable_if< std::is_same< T ,char >::value ,const char* >::type dft("%i");
typename std::enable_if< std::is_same< T ,wchar_t >::value ,const wchar_t* >::type dft (L"%i");
// doesn't work (error : type is not a member of std::enable_if< ... > !
std::basic_string< T ,std::char_traits < T > > frmt ((pszFrmt && (*pszFrmt)) ? pszFrmt : dft );
str_printf( szBuff ,iLen ,frmt.c_str() ,iNum );
return szBuff;
}
////////////////////////////////////////////////////////////////////////////////
Can I do this in a simillar way or is the working version the best way ?
Or how to do this >
I don’t need suggestion to use stringstreams (that’s not what this question is about).
Using MSVS 2010 (and sorry ,no boost).
Thank you.
Frankly, this is the only solution I can think of:
It’s not pretty, but it works.