Replaces macros by metaprogramming

V

Vincent R

Hi,

I am trying to write a framework that is supposed to work either using
native windows ce UNICODE C strings based on UTF16(wchar_t) or ansi/utf8.

So with this constraints I have in my code somlething like :

#ifdef _UNICODE
// Only copy UTF16 Value.lpszW to szStoreName(UTF16)
wcsncpy(msgStoreInfo.szStoreName, lpProp->Value.lpszW, 127);
#else
// Convert UTF16 Value.lpszW to szStoreName(ANSI)
wcstombcs(msgStoreInfo.szStoreName, lpProp->Value.lpszW, 127);
#endif

Since on wince API exists only in UNICODE version, in my previous
example lpProp->Value.lpszW is always in UTF16 but szStoreName is
defined like this :

tchar_t szStoreName[128]; ie in UNICODE it's a wchar_t while in ansi
it's the well know char.

My question is wouldn't be possible to replace those ugly defines by
some templated class that would have a method and that would copy it or
convert it in function of tchar_t type ?

template <wchar_t T>
class UniConv
{

};

template <char T>
class UniConv
{

};


and then I could write something like :

Uniconv<tchar_t>::Strncpy(msgStoreInfo.szStoreName, lpProp->Value.lpszW,
127);

I mean I want something similar ... is it possible ?
 
V

Vincent R

Vincent R a écrit :
Hi,

I am trying to write a framework that is supposed to work either using
native windows ce UNICODE C strings based on UTF16(wchar_t) or ansi/utf8.

So with this constraints I have in my code somlething like :

#ifdef _UNICODE
// Only copy UTF16 Value.lpszW to szStoreName(UTF16)
wcsncpy(msgStoreInfo.szStoreName, lpProp->Value.lpszW, 127);
#else
// Convert UTF16 Value.lpszW to szStoreName(ANSI)
wcstombcs(msgStoreInfo.szStoreName, lpProp->Value.lpszW, 127);
#endif

Since on wince API exists only in UNICODE version, in my previous
example lpProp->Value.lpszW is always in UTF16 but szStoreName is
defined like this :

tchar_t szStoreName[128]; ie in UNICODE it's a wchar_t while in ansi
it's the well know char.

My question is wouldn't be possible to replace those ugly defines by
some templated class that would have a method and that would copy it or
convert it in function of tchar_t type ?

template <wchar_t T>
class UniConv
{

};

template <char T>
class UniConv
{

};


and then I could write something like :

Uniconv<tchar_t>::Strncpy(msgStoreInfo.szStoreName, lpProp->Value.lpszW,
127);

I mean I want something similar ... is it possible ?
Hum maybe in this case a ugly define could do the trick :

#ifdef UNICODE
#define IConv_Strncpy wcsncpy
#else
#define IConv_Strncpy wcstombcs
#endif
 
A

Alf P. Steinbach

* Vincent R:
I am trying to write a framework that is supposed to work either using
native windows ce UNICODE C strings based on UTF16(wchar_t) or ansi/utf8.

So with this constraints I have in my code somlething like :

#ifdef _UNICODE
// Only copy UTF16 Value.lpszW to szStoreName(UTF16)
wcsncpy(msgStoreInfo.szStoreName, lpProp->Value.lpszW, 127);
#else
// Convert UTF16 Value.lpszW to szStoreName(ANSI)
wcstombcs(msgStoreInfo.szStoreName, lpProp->Value.lpszW, 127);
#endif

Since on wince API exists only in UNICODE version, in my previous
example lpProp->Value.lpszW is always in UTF16 but szStoreName is
defined like this :

tchar_t szStoreName[128]; ie in UNICODE it's a wchar_t while in ansi
it's the well know char.

My question is wouldn't be possible to replace those ugly defines by
some templated class that would have a method and that would copy it or
convert it in function of tchar_t type ?

template <wchar_t T>
class UniConv
{

};

template <char T>
class UniConv
{

};


and then I could write something like :

Uniconv<tchar_t>::Strncpy(msgStoreInfo.szStoreName, lpProp->Value.lpszW,
127);

I mean I want something similar ... is it possible ?

Yes it's possible although not with the syntax you've shown.

However, and sorry for calling a spade a spade but it's necessary, using
Microsoft's TCHAR support is braindead, just a load of added grunt work and
nasty bug entry vectors, unless you're supporting Windows 9x and have to use
dynamically linked MFC, which is the only known case where it can possibly save
work. That's a rather narrow and archaic market segment, I mean, how many users
of your app use it in Windows 9x, refuse to upgrade, and insist that you use
dynamically linked MFC? About zero, I'd guess. Certainly not more than 1, unless
some kind of religious cult has grown up recently. So, in summary, for nearly
all practical purposes the approach shown above is braindead, sorry.

Now, I've saved you a /lot/ of work (namely, you only have to support Unicode,
nothing more), so reciprocating you may consider posting such more-or-less
Microsoft-specific questions to a Microsoft-specific group next time. :)


Cheers & hth.,

- Alf
 
V

Vincent R

Alf P. Steinbach a écrit :
* Vincent R:
I am trying to write a framework that is supposed to work either using
native windows ce UNICODE C strings based on UTF16(wchar_t) or ansi/utf8.

So with this constraints I have in my code somlething like :

#ifdef _UNICODE
// Only copy UTF16 Value.lpszW to szStoreName(UTF16)
wcsncpy(msgStoreInfo.szStoreName, lpProp->Value.lpszW, 127);
#else
// Convert UTF16 Value.lpszW to szStoreName(ANSI)
wcstombcs(msgStoreInfo.szStoreName, lpProp->Value.lpszW, 127);
#endif

Since on wince API exists only in UNICODE version, in my previous
example lpProp->Value.lpszW is always in UTF16 but szStoreName is
defined like this :

tchar_t szStoreName[128]; ie in UNICODE it's a wchar_t while in ansi
it's the well know char.

My question is wouldn't be possible to replace those ugly defines by
some templated class that would have a method and that would copy it
or convert it in function of tchar_t type ?

template <wchar_t T>
class UniConv
{

};

template <char T>
class UniConv
{

};


and then I could write something like :

Uniconv<tchar_t>::Strncpy(msgStoreInfo.szStoreName,
lpProp->Value.lpszW, 127);

I mean I want something similar ... is it possible ?

Yes it's possible although not with the syntax you've shown.

However, and sorry for calling a spade a spade but it's necessary, using
Microsoft's TCHAR support is braindead, just a load of added grunt work
and nasty bug entry vectors, unless you're supporting Windows 9x and
have to use dynamically linked MFC, which is the only known case where
it can possibly save work. That's a rather narrow and archaic market
segment, I mean, how many users of your app use it in Windows 9x, refuse
to upgrade, and insist that you use dynamically linked MFC? About zero,
I'd guess. Certainly not more than 1, unless some kind of religious cult
has grown up recently. So, in summary, for nearly all practical purposes
the approach shown above is braindead, sorry.

Now, I've saved you a /lot/ of work (namely, you only have to support
Unicode, nothing more), so reciprocating you may consider posting such
more-or-less Microsoft-specific questions to a Microsoft-specific group
next time. :)


Cheers & hth.,

- Alf
Braidead or not it's used on MS platform so I did the following :

template <typename T>
struct IConv
{
int Strncpy(T dest, const wchar_t* src, int nLen) {;}
};

template <>
int IConv<char>::Strncpy(char dest, const wchar_t* src, int nLen)
{
return wcstombs(dest, src, nLen);
}

template <>
int IConv<wchar_t>::Strncpy(wchar_t dest, const wchar_t* src, int nLen)
{
return wcsncpy(dest, src, nLen);
}
 
V

Vincent R

Braidead or not it's used on MS platform so I did the following :
I would say that my question is not MS specific it's more about template
specializations and I think it's more adapted here !!!!
After if I handle a TCHAR or some exotic type what is the problem ?

So I wanted to say I tried this :

template <typename T>
struct IConv
{
int Strncpy(T dest, const wchar_t* src, int nLen) {;}
};

template <>
int IConv<char>::Strncpy(char* dest, const wchar_t* src, size_t nLen)
{
return ::wcstombs(dest, src, nLen);
}

template <>
int IConv<wchar_t>::Strncpy(wchar_t* dest, const wchar_t* src, size_t nLen)
{
return ::wcsncpy(dest, src, nLen);
}


But of course it doesn't work :
1>c:\cygwin-1.7\home\vincent\projects\gynoid\src\gynoid\src\UniConv.hxx(16)
: error C2244: 'IConv<T>::Strncpy' : unable to match function definition
to an existing declaration
1> with
1> [
1> T=char
1> ]
1>
c:\cygwin-1.7\home\vincent\projects\gynoid\src\gynoid\src\UniConv.hxx(9)
: see declaration of 'IConv<T>::Strncpy'
1> with
1> [
1> T=char
1> ]
1> definition
1> 'int IConv<T>::Strncpy(char *,const wchar_t *,size_t)'
1> with
1> [
1> T=char
1> ]
1> existing declarations
1> 'int IConv<T>::Strncpy(T,const wchar_t *,int)'
1> with
1> [
1> T=char
1> ]
 
V

Vincent R

Finally the following seems to compile, need to test more:


template <typename T>
struct IConv
{
static void Strncpy(T* dest, const wchar_t* src, size_t nLen) {;}
};

template <>
void IConv<char>::Strncpy(char* dest, const wchar_t* src, size_t nLen)
{
::wcstombs(dest, src, nLen);
return;
}

template <>
void IConv<wchar_t>::Strncpy(wchar_t* dest, const wchar_t* src, size_t nLen)
{
::wcsncpy(dest, src, nLen);
return ;
}
 
A

Alf P. Steinbach

* Vincent R:
Braidead or not it's used on MS platform so I did the following :
I would say that my question is not MS specific it's more about template
specializations and I think it's more adapted here !!!!
After if I handle a TCHAR or some exotic type what is the problem ?

So I wanted to say I tried this :

template <typename T>
struct IConv
{
int Strncpy(T dest, const wchar_t* src, int nLen) {;}
};

template <>
int IConv<char>::Strncpy(char* dest, const wchar_t* src, size_t nLen)
{
return ::wcstombs(dest, src, nLen);
}

template <>
int IConv<wchar_t>::Strncpy(wchar_t* dest, const wchar_t* src, size_t nLen)
{
return ::wcsncpy(dest, src, nLen);
}


But of course it doesn't work :
1>c:\cygwin-1.7\home\vincent\projects\gynoid\src\gynoid\src\UniConv.hxx(16)
: error C2244: 'IConv<T>::Strncpy' : unable to match function definition
to an existing declaration
1> with
1> [
1> T=char
1> ]
1>
c:\cygwin-1.7\home\vincent\projects\gynoid\src\gynoid\src\UniConv.hxx(9)
: see declaration of 'IConv<T>::Strncpy'
1> with
1> [
1> T=char
1> ]
1> definition
1> 'int IConv<T>::Strncpy(char *,const wchar_t *,size_t)'
1> with
1> [
1> T=char
1> ]
1> existing declarations
1> 'int IConv<T>::Strncpy(T,const wchar_t *,int)'
1> with
1> [
1> T=char
1> ]

You have 3 options:

A. Do as I suggested originally, and really, it'll save you a lot of work.

B. Make Strncpy a templated free-standing routine instead of a member routine.

C. Specialize the complete class: you can't specialize just a member routine.

With approach C you'd write e.g. (off the cuff)

template< typename Char > struct Conv;

template<> struct Conv<char>
{
// Tada!
};

template<> struct Conv<wchar_t>
{
// Todo!
}

Uh, except that the last one may cause DevStudio (I'm assuming that IDE because
of the Microsoft-specificity) to insist that you have some added work to do.

Which, in a sense, would be right, but for the wrong reason, as is usual when
apparently something is right... ;-)


Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Alf P. Steinbach:
C. Specialize the complete class: you can't specialize just a member
routine.

I'm sorry, I apologize, but the above statement seems to be in error.

I discovered, when trying to check the validity of that statement, that I have
real difficulties parsing and making sense of the standard's section on
templates, and that some of it, regarding what can and can't be specialized, is
internally self-contradictory (discussed in old thread in [comp.std.c++]).

Even the following is apparently OK:


<code>
#include <iostream>

void say( char const s[] ) { std::cout << s << std::endl; }

template <typename T>
struct Foo
{
virtual void a() { say( "general a" ); }
virtual void b() { say( "b" ); }
};

template<> void Foo<char>::a() { say( "specialized a" ); }

int main()
{
Foo<char> o;
o.a();
o.b();
}
</code>


I don't know where I got the idea from that one would have to specialize the class.

But anyway, I apologize for the disinformation.


Cheers,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top