C++ conversion operator between types in other libraries
For convenience, I'd like to be able to cast between two types defined in other libraries. (Specifically, QString
from the Qt library and UnicodeString
from the ICU library.) Right now, I have created utility functions in a project namespace:
namespace MyProject 开发者_StackOverflow{
const icu_44::UnicodeString ToUnicodeString(const QString& value);
const QString ToQString(const icu_44::UnicodeString& value);
}
That's all well and good, but I'm wondering if there's a more elegant way. Ideally, I'd like to be able to convert between them using a cast operator. I do, however, want to retain the explicit nature of the conversion. An implicit conversion should not be possible.
Is there a more elegant way to achieve this without modifying the source code of the libraries? Some operator overload syntax, perhaps?
You could always do exactly what you're doing but make it look more like casting. There may even be some reasonable argument for doing so, such as being able to override for more types and retain the same syntax.
Consider:
template < typename DestType, typename SourceType >
DestType string_cast(SourceType const& source)
{
return string_cast_impl<DestType,SourceType>::apply(source);
}
template < typename DestType, typename SourceType >
struct string_cast_impl;
template < >
struct string_cast_impl<QString,icu_44::UnicodeString>
{
QString apply(icu_44::UnicodeString const& val) { return MyProject::ToQString(value); }
};
// etc...
You might consider not using the impl struct (because you don't need to partially specialize...ever), or you might consider enhancing it so that you can use enable_if. At any rate, you'd have a common interface for string type conversion such that you don't need to remember what function to call...just call string_cast<Dest>(source).
Edit: come to think of it, I'm doing what you're doing in one of my projects to convert from std::string to/from std::wstring. I think I'll use this alternative to replace that.
If what you're striving for is to be able to say
QStrign qs;
UnicodeString us(qs);
or
UnicodeString us;
QString qs(us);
then no, you can't do that unless you can change either of the classes. You can, of course, introduce a new string:
NewString ns;
UnicodeString us(ns);
QString qs(us);
NewString nsus(us);
NewString nsqs(qs);
I'm not sure about this approach's elegance though, compared with your two explicit conversion functions.
A possible solution would be to wrap these types and provide explicit conversion constructors. I take it you cannot modify the source of both QString
and icu_44::UnicodeString
which would be the most natural place for the conversion constructors to reside. The use of the keyword explicit
prohibits implicit conversion, hence conversions can only occur when you write QString converted(original)
with original
a value of typeicu_44::UnicodeString
or vice versa.
The only problem with this approach is that you have to wrap your data types. I don't know whether you'll ever need more operations on these types currently not provided in the actual libraries or not, but if that's the case, wrapping is a possible way to go
Side question, do you mean to use the 4.4 namespace directly and not just icu::UnicodeString ?
精彩评论