Re: Cheap (simple, efficient) solution for literal strings in templates?

From: Alf P. Steinbach (alfps_at_start.no)
Date: 03/24/05


Date: Thu, 24 Mar 2005 12:24:49 GMT


* Ioannis Vranos:
> * Alf P. Steinbach:
>
> > Depending on a template type argument Char I'd like a literal string,
> > and for that matter also literal char constants, to be 'char' or 'wchar_t'
> > base type, i.e.
> >
> > template< typename Char >
> > bool isPassword( std::basic_string<Char> const& s )
> > {
> > return s == "password"; // Cheap solution for Char === wchar_t?
> > }
> >
> > The cheapest solution I could make to work involved a class + macro
> > like
> >
> > struct literal_string
> > {
> > wchar_t const* myWide;
> > char const* myNarrow;
> >
> > literal_string( wchar_t const* w, char const* n )
> > : myWide( w ), myNarrow( n )
> > {}
> >
> > operator wchar_t const* () const { return myWide; }
> > operator char const* () const { return myNarrow; }
> > };
> >
> > #define S( a ) literal_string( a, L ## a )
> >
> > I couldn't make that work with the strings as template arguments.
>
>
> I did not understood what exactly you want to do, however you can
> "store" string literals like this:
>
>
> #include <vector>
>
> int main()
> {
> using namespace std;
>
> vector<char *> charLiterals;
>
> charLiterals.push_back("literal1");
> charLiterals.push_back("whatever");
>
> vector<wchar_t *> wcharLiterals;
>
> wcharLiterals.push_back(L"literal1");
> wcharLiterals.push_back(L"whatever");
>
>
> char *charlits[5]= {"lit1", "lit2" };
>
> charlits[3]= "whatever";
>
> wchar_t *wcharlits[5];
>
> wcharlits[0]= L"wide character literal";
> }

Well, best of all I'd like the ability to just write a string directly
where it's used, and that's what the solution I sketched above provided:
if the context requires 'char', then it's 'char', and ditto for 'wchar_t'.

For efficiency, however, and also for the ability to use as template
arguments and other compile-time stuff, it would be nice to declare the
strings at namespace scope, even in a header file.

Here's what I came up with for that; it's ugly, isn't it? :-)

================================================================================
struct dummy_type {};

template< template<typename Char> class LiteralStringDefiner >
struct cameleon_string_
{
    operator char const* () { return LiteralStringDefiner<char>::s; }
    operator wchar_t const* () { return LiteralStringDefiner<wchar_t>::s; }
};

#define DEFINE_CAMEL( name, literal_string ) \
namespace literal \
{ \
    template< typename Dummy> struct name ## _char { static char const s[]; }; \
    template< typename Dummy> char const name ## _char<Dummy>::s[] = "s"; \
                                                                                \
    template< typename Dummy> struct name ## _wchar_t { static wchar_t const s[]; };\
    template< typename Dummy> wchar_t const name ## _wchar_t<Dummy>::s[] = L"s"; \
                                                                                \
    template< typename Char> struct name ## _; \
                                                                                \
    template<> struct name ## _<char>: name ## _char<dummy_type> {}; \
    template<> struct name ## _<wchar_t>: name ## _wchar_t<dummy_type> {}; \
                                                                                \
    typedef cameleon_string_<name ## _> name; \
}

DEFINE_CAMEL( huh, "duh" )
================================================================================

With that I can write code like

================================================================================
template< typename Char >
void display( Char const* )
{
}

template< typename Char >
bool is_password( std::basic_string<Char> const& s )
{
    display<Char>( literal::huh() );
    return s == literal::huh_<Char>::s;
}

int main()
{
    is_password<char>( "birthdate" );
    is_password<wchar_t>( L"spouse" );
}
================================================================================

-- 
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


Relevant Pages

  • Re: About template!
    ... Well, static storage, global linkage, named. ... So you can't use a string literal, or a const string (cos it'll be given ... Then your template can be: ... template <const char* p> ...
    (microsoft.public.vc.atl)
  • injection_projection code
    ... because of hex encoding. ... a row in the template. ... Sanitize string to protect against email header injection. ... void injection_protection(char *s) ...
    (freebsd-isp)
  • Re: Detecting if type is char*
    ... I want to disallow using sizeof on type char*, by providing a template ... It seems to me that you want sizeof to work with everything that isn't an array, not just everything that isn't a char pointer. ... enum; ...
    (microsoft.public.vc.language)
  • Re: Word 2007 style editing and corruption
    ... Almost very time, multiple unlinked styles (char char char, etc.) were ... Do this to the template and all files based on the ... not use Word’s theme-based style sets at all. ... acquiring those large hanging indents and space before. ...
    (microsoft.public.word.application.errors)
  • Re: style pane shows unwanted styles when word re-opened
    ... "Stefan Blom" wrote: ... cleaned up my normal template again, ... So seems some of the stlye manager choices get lost when saving w2007 to ... char was an old glitch associated with tables in word 2003 and I was ...
    (microsoft.public.word.docmanagement)