* 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" );
}
================================================================================