[type_erasure] Difficulties with const

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

* ping *
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
--------------------------------------------------------------------------------
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

AMDG On 09/13/2012 01:42 PM, Christophe Henry wrote:
* ping *
I'm sorry. I don't think I received the original message.
<snip> 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); } }; } }
<snip>
This compiles and outputs as expected.
Problem 1: This will not compile std::cout << "data: " << (*it).getName() << std::endl;
concept_interface<...>::getName needs to be declared const for this to work.
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.
For a constant member function use: has_getName<std::string const&(), const _self>
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?
In Christ, Steven Watanabe

Hi Steven, sorry, I just came now to try it out.
concept_interface<...>::getName needs to be declared const for this to work.
Ok, got it.
For a constant member function use:
has_getName<std::string const&(), const _self>
Ok, now it works like a charm! Thanks, Christophe
participants (2)
-
Christophe Henry
-
Steven Watanabe