Casting problems with BOOST_FOREACH and cxxtest plugin

170 views Asked by At

I'm currently working on a project where I use:

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!

  1. 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

  2. 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.

  3. Implementing an extension that would fix this error. I don't know if it should be done in the const_cast_helper or the rvalue_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!

1

There are 1 answers

0
Matija Lukic On BEST ANSWER

After some more digging, I managed to find a workaround. I defined a symbol DEREFEREE_NO_CONST_CAST to my build configuration. That prevented const_cast_helper from getting compiled. Hopefully no bugs will creep in, the tests are running now...