Boost logo

Boost :

Subject: [boost] [type_erasure] Difficulties with const
From: Christophe Henry (christophe.j.henry_at_[hidden])
Date: 2012-08-30 05:20:41


Hi Steven,

I have a const problem. Consider the following classes:

struct Something
{
  Something(const char* n): myName(n){}
  std::string const& getName()const
  {
    return myName;
  }
  std::string myName;
};

struct Container
{
  typedef std::vector< AnyNameable > PublicData;

  Container()
  {
    Something s1("bla");
    Something s2("blabla");
    myData.push_back(s1);
    myData.push_back(s2);
  }

  PublicData getData()const
  {
    PublicData res;
    for (Data::const_iterator it = myData.begin(); it != myData.end() ; ++it)
    {
      res.push_back(AnyNameable(*it));
    }
    return res;
  }
private:
  typedef std::vector< Something > Data;
  Data myData;
};

Container is simply a class returning its "Something", hidden behind
AnyNameable (nice way to realize C++ Coding Standards Item 42 BTW).

I have a simple test function:
void test()
{
  Container c;
  Container::PublicData data = c.getData();
  for (Container::PublicData::const_iterator it = data.begin(); it !=
data.end() ;++it)
  {
    AnyNameable a(*it);
    std::cout << "data: " << a.getName() << std::endl;
    // auxiliary question: why does this not work if I use const _self&?
    //std::cout << "data: " << (*it).getName() << std::endl;
  }
}

int main()
{
  test();
  return 0;
}

Now comes the interesting part. If I define AnyNameable using the
concept interface, all goes (almost) well:

template<class C, class T>
struct getName
{
    static T apply(C const& cont) { return cont.getName(); }
};
namespace boost {
namespace type_erasure {
template<class C, class T, class Base>
struct concept_interface< ::getName<C, T>, Base, C> : Base
{
    T getName()
    { return call(::getName<C, T>(), *this); }
};
}
}

typedef any<
          mpl::vector<
              getName<_self,std::string const&>,
              relaxed_match,
              copy_constructible<>,
              typeid_<>
>,
           const _self&
>
AnyNameable;

This compiles and outputs as expected.

Problem 1: This will not compile
std::cout << "data: " << (*it).getName() << std::endl;

Hmmm ok not so bad. I'll gladly pay the extra line. (interestingly, it
would compile and work without const)

Problem 2: if I use the MEMBER macro:

BOOST_TYPE_ERASURE_MEMBER((has_getName), getName, 0);
typedef any<
          mpl::vector<
              has_getName<std::string const&()>,
              relaxed_match,
              copy_constructible<>,
              typeid_<>
>,
           const _self&
>
AnyNameable;

Then the code does not compile, unless I accept to give up all of my consts.
On one hand, I will find it a easier job to sell type_erasure with the
macro, OTOH, I will not give up my consts ;-)

Would it be possible to have the macro AND const-correctness?

Attached, a small test with the complete code.

Thanks,
Christophe




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