开发者

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 ?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜