Boost logo

Boost Users :

Subject: Re: [Boost-users] How to get the basic_path specialization for TCHAR ?
From: Richard (legalize+jeeves_at_[hidden])
Date: 2010-07-30 04:00:28


[Please do not mail me a copy of your followup]

boost-users_at_[hidden] spake the secret code
<i2soqi$tgd$1_at_[hidden]> thusly:

>Richard wrote:
>> [Please do not mail me a copy of your followup]
>>
>> boost-users_at_[hidden] spake the secret code
>> <i2pv64$vp8$1_at_[hidden]> thusly:
>>
>>> Is there a nice why to select a basic_path specialization with the
>>> current with of TCHAR ?
>>
>> TCHAR is just a typedef for char or wchar_t. So anyplace you would
>> use char or wchar_t as a template argument you can use TCHAR.
>
>Ok and how could I specialize basic_path with TCHAR to get a path if
>TCHAR is char, and a wpath if TCHAR is wchar_t ?

Looking at path.hpp in my boost 1.40 distribution, we have for narrow
strings:

    struct path_traits;
    typedef basic_path< std::string, path_traits > path;

    struct path_traits
    {
      typedef std::string internal_string_type;
      typedef std::string external_string_type;
      static external_string_type to_external( const path &,
        const internal_string_type & src ) { return src; }
      static internal_string_type to_internal(
        const external_string_type & src ) { return src; }
    };

...and for wide strings:

# ifndef BOOST_FILESYSTEM_NARROW_ONLY

    struct BOOST_FILESYSTEM_DECL wpath_traits;
    
    typedef basic_path< std::wstring, wpath_traits > wpath;

    struct BOOST_FILESYSTEM_DECL wpath_traits
    {
      typedef std::wstring internal_string_type;
# ifdef BOOST_WINDOWS_API
      typedef std::wstring external_string_type;
      static external_string_type to_external( const wpath &,
        const internal_string_type & src ) { return src; }
      static internal_string_type to_internal(
        const external_string_type & src ) { return src; }
# else
      typedef std::string external_string_type;
      static external_string_type to_external( const wpath & ph,
        const internal_string_type & src );
      static internal_string_type to_internal(
        const external_string_type & src );
# endif
      static void imbue( const std::locale & loc );
      static bool imbue( const std::locale & loc, const std::nothrow_t & );
    };

# endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY

Remember that std::string is a typedef for std::basic_string<char> and
std::wstring is a typedef for std::basic_string<wchar_t>.

When dealing with TCHAR, I'll often define tstring as a typedef for
std::basic_string<TCHAR>, making tstring the same as std::string in an
ansi build and the same as std::wstring in a unicode build.

In the case of the path_traits and wpath_traits, they've defined two
different traits struct names instead of a singly named struct with a
template specialization. You could handle this with the
preprocessor:

#if defined(UNICODE)
#define tpath_traits wpath_traits
#else
#define tpath_traits path_traits
#endif

typedef std::basic_string<TCHAR> tstring;
typedef basic_path< tstring, tpath_traits > tpath;

(You may need to handle the boost::filesystem namespace in the above
snippet. YMMV.)

Doing it that way would repeat the least amount of stuff from path.hpp.

Duplication is bad and sometimes the way to eliminate duplication is
to use the preprocessor.

-- 
"The Direct3D Graphics Pipeline" -- DirectX 9 draft available for download
 <http://legalizeadulthood.wordpress.com/the-direct3d-graphics-pipeline/>
      Legalize Adulthood! <http://legalizeadulthood.wordpress.com>

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net