mardi 24 mai 2016

const_cast and std::move to remove constness from non-reference

I have an external library which I can not modify. The library declares a template function that for some reason returns const non-reference object:

template<class C>
const C foo();

I have another external library which I can not modify too. The library declares a class that is non-copyable and has a move constructor from a non-const object only:

struct bar {
    bar() {}
    bar(const bar&)=delete;
    bar(bar&&) {}
};

Now I heed to use foo<bar>. A simple usage:

bar buz() {
    return foo<bar>();
}

fails with

main.cpp: In function 'bar buz()':
main.cpp:13:21: error: use of deleted function 'bar::bar(const bar&)'
     return foo<bar>();
                     ^
main.cpp:8:5: note: declared here
     bar(const bar&)=delete;
     ^~~

which makes sense, and no simple workaround make the code compile.

However, if I add some more complex workaround:

bar buz() {
    return const_cast<bar&&>(std::move(foo<bar>()));
}

it compiles and the whole code work as expected (not only the simplified example above, but my real code too).

However, it is safe, or am I running into some undefined behavior? Is there any better workaround?


I have read and I understand questions about returning const from functions (1, 2), and the common answer there seems to be that returning const objects is discouraged in modern C++, but my question is not about it, but about how can I workaround the situation when an external library returns const object.

Aucun commentaire:

Enregistrer un commentaire