I'm currently working on a project where I use:
- boost libraries v1.39
- Eclipse CDT (Juno) and Cygwin
- CxxTest plugin: http://wiki.web-cat.org/WCWiki/EclipsePlugins/CxxTestPlugin
and I've run into a issue regarding the const_cast
. I've searched high and low and found no sources online that can help me. The problem appears when I call BOOST_FOREACH
within a test method. I keep getting the following error:
/usr/include/boost/foreach.hpp: In member function
'boost::foreach_detail_::rvalue_probe<T>::operator T&() const [with T =
boost::unordered_map<std::basic_string<char>, std::basic_string<char> >]':
... instantiated from here /usr/include/boost/foreach.hpp:476:90:
error: invalid cast from type
Dereferee::const_cast_helper<boost::foreach_detail_::rvalue_probe<boost::unordered_map<std
::basic_string<char>, std::basic_string<char> > >*>
to type 'boost::unordered_map<std::basic_string<char>, std::basic_string<char> >*
const_cast_helper
I started dissecting the problem and found out that the const_cast operator is overloaded for the purpose of some run-time checking, I don't know what. All in all, there is a Dereferee::const_cast_helper
that is a part of the cxxtest dependecies, an overload of the const_cast operator.
This helper undefines the const_cast operator (!)
#ifdef const_cast
#undef const_cast
#endif
and at the end reintroduces const_cast operator:
#define const_cast ::Dereferee::const_cast_helper
so that every time const_cast is called, the appropriate constructor of this helper is called. Constructors accept pointers, references, const pointers, and const references.
The source is here: https://github.com/web-cat/dereferee-with-cxxtest/blob/master/Dereferee/include/dereferee/const_cast.h
rvalue_probe
Boost also plays around with casts in order to see if the collection being iterated over is a lvalue or rvalue, in order to avoid copying it / recalculating the expression.
The compiler complains on the following:
template<typename T>
struct rvalue_probe
{
...
operator T &() const { return *reinterpret_cast<T *>(const_cast<rvalue_probe *>(this)); }
};
In my case, T is the boost::unordered_map and somehow the combination of this cast and the helper's overload breaks...
Ways to solve it?
I examined what the possible solutions could be, but I don't know how to actually implement them, I don't have that much C++ experience. I don't care one bit if I'll have these compile-time checks in my tests, I can work around that. So, any help in any of the three directions would be most helpful!
Disabling boost's rvalue checking, playing with BOOST_WORKAROUND and literals defined in foreach.hpp
BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION BOOST_FOREACH_NO_RVALUE_DETECTION BOOST_FOREACH_NO_CONST_RVALUE_DETECTION BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
Disabling this
const_cast_helper
. When I run my test programs (different project than then test project), my code compiles and runs as expected, the overload of const_cast created problems.Implementing an extension that would fix this error. I don't know if it should be done in the
const_cast_helper
or thervalue_probe
but it didn't do any good.
template <typename T> const_cast_helper(rvalue_probe<U>* value_to_cast) : cast_value(const_cast<U*>(value_to_cast)) { }
Thank you for your input in advance!
After some more digging, I managed to find a workaround. I defined a symbol
DEREFEREE_NO_CONST_CAST
to my build configuration. That preventedconst_cast_helper
from getting compiled. Hopefully no bugs will creep in, the tests are running now...