Pregunta

I'm working on a legacy library that needs to be backwards compatible with C++03, but is also forward compatible to take advantage of C++11 features like move semantics and explicit casting.

So, is it possible to emulate explicit casting in C++03? I know obviously about the explicit bool (or "safe" bool) idiom - but that's only for casting to a boolean type. Is it possible to emulate a general explicit cast operator in C++03?

I checked around, and found a discussion about this in a book called "Imperfect C++ : Practical Solutions for Real-Life Programming".

In this book, they discuss some ideas about emulating an explicit cast in C++03 (the book was written before C++11). Ultimately, they recommend creating an explicit_cast<T> template. However, I don't like that solution because I want users to simply be able to use static_cast<T>, which works fine in C++11.

So, another solution was to force the compiler to do two conversions, which will disallow implicit conversions. An example of that would be something like:

class int_cast
{
    public:

    int_cast(const int& v) : m_value(v)
    { }

    operator int() const
    {
        return m_value;
    }

    private:

    int m_value;
};

struct Foo
{
    Foo()
    {
        x = 10;
    }

    operator int_cast() const
    {
        return int_cast(x);
    }

    int x;
};

Here, a Foo should be explicitly convertible to int, but not implicitly. (This code is lifted almost verbatim from Imperfect C++, except in their example they are converting a custom Time object to a std::tm.

However, this doesn't actually work, at least not using GCC 4.7.2:

Foo f;
int x = static_cast<int>(f);

This results in :

test3.cpp: In function ‘int main()’:
test3.cpp:44:28: error: invalid static_cast from type ‘Foo’ to type ‘int’

So I guess "Imperfect C++" is wrong here. The compiler wasn't able to convert a Foo to an int, even with an explicit cast. (Maybe this worked on older compilers?) So, is there anyway to emulate this in C++03 (without using a custom cast operator)?

¿Fue útil?

Solución

"Imperfect C++" is right, because it uses a custom "keyword" - actually a function name masquerading as a keyword (not unlike eg.: Tribool's indeterminate). If you try to static_cast you crash against the limitation that the language can only accept conversion chains that involve up to one user-defined type, whereas you have two conversions - from "Foo" to "int_cast" and from there to int.

If you want specifically to be able to static_cast then you'll probably have to hack something with macros to supersede normal static_cast... and accept to live in Undefined Behaviour Land. My preferred choice is to actually work in the inverse direction: simply use explicit_cast and use a macro to redefine it as a static_cast invocation when in C++11 mode. I use explicit cast in my C++ backports toolkit and thus in all the C++ code I write, and I have found no important issues so far.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top