Boost logo

Boost :

Subject: [boost] [type_erasure] issue when taking any<> by const ref
From: Thomas Petit (thomas.petit33_at_[hidden])
Date: 2012-11-12 18:33:06


Hi,
I'm playing with the boost type erasure library (from the sandbox) and hit
some issues.

Imagine that I have an any accepting some concept :
> typedef any<concept1<>, concept2<>> some_any_t;
and a std::vector to put a few any in it :
> std::vector<some_any_t> v;
Then If I iterate over the vector by taking each element by reference
>for(some_any_t& : v)
>{
>}
everything is fine and consistent with why I expect.

However if I iterate by taking element by const ref
>for(const some_any_t& : v)
>{
>}
then some issue appears.

Here is an example showing the problems (with one any using a concept
defined by BOOST_TYPE_ERASURE_FREE
 and one any using a concept defined by BOOST_TYPE_ERASURE_MEMBER)

...................................................

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/type_erasure/member.hpp>

namespace mpl = boost::mpl;
namespace te = boost::type_erasure;

template <typename T>
void free(const T& t)
{
    std::cout << typeid(t).name() << std::endl;
    std::cout << "default free\n";
}

void free(const int& i)
{
    std::cout << typeid(i).name() << std::endl;
    std::cout << "int\n";
}

BOOST_TYPE_ERASURE_FREE((has_free), free, 1);
template<class T = te::_self>
struct free_concept : mpl::vector<has_free<void(const T&)> > {};

typedef te::any<mpl::vector<te::copy_constructible<>, free_concept<>>>
any_free_t;

struct Base
{
    virtual void member() const
    {
        std::cout << "Base member\n";
    }
};

struct Derived : public Base
{
    virtual void member() const
    {
        std::cout << "Derived member\n";
    }
};

BOOST_TYPE_ERASURE_MEMBER((has_member), member, 0)
struct member_concept : mpl::vector<has_member<void()> > {};
typedef te::any<mpl::vector<te::copy_constructible<>, member_concept>>
any_member_t;

int main()
{
    any_free_t af1(5);
    any_free_t af2(5.0);
    std::vector<any_free_t> v;
    v.push_back(af1);
    v.push_back(af2);

    for(any_free_t& af : v)
    {
        free(af);
    }

    Base b;
    Derived d;
    std::vector<any_member_t> v2;
    v2.push_back(b);
    v2.push_back(d);

    for(any_member_t& am : v2)
    {
        am .member();
    }
}
.......................................................

In the previous code, if add a const here :

for(const any_free_t& af : v)
{
    free(af);
}

then instead of calling the int overload of the free function and the
template overload with a double type,
the templated free function is called both time but, unfortunately the type
of T is always the same as the any.

Another point, if I add a const here :
for(const any_member_t& am : v2)
{
     am .member();
}
then I get a compile error. (with visual 2012 and gcc 4.7)

I'm a bit puzzled by this behavior. Are any<> types never supposed to be
taken by const ref ?
How can we iterate over anys while preserving constness ?

Thanks.
Thomas.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk