Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

To initialize a string

46 views
Skip to first unread message

Daniel

unread,
Sep 19, 2017, 10:22:13 PM9/19/17
to
I need to be able to initialize a basic_string to a constant in a generic fashion, where the constant is restricted to ascii characters, e.g.

#include <string>
#include <vector>
#include <iostream>

template <class CharT>
struct A
{
const std::vector<std::basic_string<CharT>> v =
{
std::basic_string<CharT>{'t','r','u','e'},
std::basic_string<CharT>{'f','a','l','s','e'}
};
};

int main()
{
A<char> a;
A<wchar_t> b;

std::cout << a.v[0] << std::endl;
std::wcout << b.v[1] << std::endl;
}

However, I also want to support a compiler that doesn't support a basic_string<CharT> std::initializer_list<CharT> constructor. Any suggestion for a simple workaround that only requires a pre C++ 11 string constructor?

Thanks,
Daniel

Alf P. Steinbach

unread,
Sep 20, 2017, 2:36:38 AM9/20/17
to
For pre-C++11 (C++03 and C++98) the T in std::basic_string<T> is in
practice either `char` or `wchar_t` – because it's too much work to
specialize `std::character_traits` for any other type, and without such
specialization std::basic_string<T> is very limited, useless.

So, I suggest you use a macro to define pairs of literals:

#define DEF_LITERAL( name, lit ) \
char const* const bytestr_name = lit; \
wchar_t const* const widestr_name = L # lit; \
template< class Ch ) Ch const* name(); \
char const* name<char>() { return bytestr_name; } \
wchar_t const* name<char>() { return widestr_name; }

Then use like

DEF_LITERAL( baluba, "Real baluba!" )

void foo()
{
wstring s = baluba<wchar_t>();
}

Disclaimer: code not seen by compiler.


Cheers & hth.,

- Alf

Daniel

unread,
Sep 20, 2017, 12:51:05 PM9/20/17
to
On Wednesday, September 20, 2017 at 2:36:38 AM UTC-4, Alf P. Steinbach wrote:
>
> So, I suggest you use a macro to define pairs of literals:
>
> #define DEF_LITERAL( name, lit ) \
> char const* const bytestr_name = lit; \
> wchar_t const* const widestr_name = L # lit; \
> template< class Ch ) Ch const* name(); \
> char const* name<char>() { return bytestr_name; } \
> wchar_t const* name<char>() { return widestr_name; }
>
> Then use like
>
> DEF_LITERAL( baluba, "Real baluba!" )
>
> void foo()
> {
> wstring s = baluba<wchar_t>();
> }
>
> Disclaimer: code not seen by compiler.
>
Silly compiler should have known what you meant, but this one works:

#define DEF_LITERAL( name, lit ) \
template< class Ch > Ch const*const name(); \
template<> char const * const name<char>() { return lit; } \
template<> wchar_t const*const name<wchar_t>() { return L ## lit; }

DEF_LITERAL(baluba, "Real baluba!")

int main()
{
std::cout << baluba<char>() << std::endl;
std::wcout << baluba<wchar_t>() << std::endl;
}

Thanks,
Daniel

Alf P. Steinbach

unread,
Sep 20, 2017, 3:22:57 PM9/20/17
to
Oh, yes.

Note that (for undisclosed reasons) I'm unfortunately often stupid these
days, like the above # . So, I forgot to discuss issues of separate
compilation and inlining in header. Hopefully others here will chime in.


Cheers!,

- Alf

Daniel

unread,
Sep 20, 2017, 4:43:32 PM9/20/17
to
The linker thought to mention that, changed to

namespace detail {
#define DEF_LITERAL( name, lit ) \
template< class Ch > Ch const*const name(); \
template<> inline char const * const name<char>() { return lit; } \
template<> inline wchar_t const*const name<wchar_t>() { return L ## lit; }

Daniel
0 new messages