Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to write custom cast operators in C++ (like `static_cast`)?

Tags:

c++

casting

I get this idea and attempted to write a string_cast casting operator to cast between C++ strings.

template <class OutputCharType>
class string_cast
{
    public:
        template <class InputCharType>
        operator std::basic_string<OutputCharType>(const std::basic_string<InputCharType> & InputString)
        {
            std::basic_string<OutputCharType> OutputString;
            const std::basic_string<InputCharType>::size_type LENGTH = InputString.length();
            OutputString.resize(LENGTH);
            for (std::basic_string<OutputCharType>::size_type i=0; i<LENGTH; i++)
            {
                OutputString[i] = static_cast<OutputCharType>(OutputString[i]);
            }
            return OutputString;
        }
};

I tried to use it like this:

std::string AString("Hello world!");
std::cout  << AString << std::endl;
std::wcout << string_cast<wchar_t>(AString) << std::endl; // ERROR

The error message is:

Error   C2440   '<function-style-cast>': cannot convert from
'const std::string' to 'string_cast<wchar_t>'

Is this impossible in C++, or am I missing something in my code?

like image 433
hkBattousai Avatar asked Dec 11 '22 19:12

hkBattousai


2 Answers

You may write free function with signature:

template <typename OutputCharType, typename InputCharType>
std::basic_string<OutputCharType>
string_cast(const std::basic_string<InputCharType>& InputString)
like image 71
Jarod42 Avatar answered Dec 13 '22 09:12

Jarod42


It looks like you just want a non-member function rather than a functor:

template <class OutputCharType, class InputCharType>
std::basic_string<OutputCharType> 
string_cast(const std::basic_string<InputCharType> & InputString)
{
    std::basic_string<OutputCharType> OutputString;
    const auto LENGTH = InputString.length();
    OutputString.resize(LENGTH);
    for (auto i=0; i<LENGTH; i++)
    {
        OutputString[i] = static_cast<OutputCharType>(OutputString[i]);
    }
    return OutputString;
}

Also note that I changed the size_type types to auto. That's because they are dependent names, so you'd need to use typename to use them as types (MSVC might let you get away without it, but this is not portable):

const std::basic_string<InputCharType>::size_type LENGTH = InputString.length();
//change to
const typename std::basic_string<InputCharType>::size_type LENGTH = InputString.length();    
//    ^^^^^^^^

This gets pretty ugly, so it's best to just use auto. If you can't use C++11, you could create InSize and OutSize typedefs.

like image 32
TartanLlama Avatar answered Dec 13 '22 08:12

TartanLlama