Re: [boost] [type_erasure] Review started (July 18-27, 2012)

AMDG On 08/02/2012 12:29 PM, Larry Evans wrote:
On 07/18/12 00:13, Lorenzo Caminiti wrote:
Hello all,
*** The review of Steven Watanabe's proposed Boost.TypeErasure library begins on July 18, 2012 and ends on July 27, 2012. *** [snip] Should type_erasure be accepted into Boost?
Answer: No, not yet. Why(in order of importance):
1) any<C,T>::any(U&, static_binding<Map>&) bug
The bug reported here: http://article.gmane.org/gmane.comp.lib.boost.devel/233101 should be resolved.
The bug is just too dangerous for the resolution to be delayed.
I added a static assert.
<snip>
My review:
1. What is your evaluation of the design?
Good, except for:
[need variadic static_binding ctor]:
The any CTOR:
template<class U, class Map> any(U & arg, const static_binding< Map > & binding);
documented here:
http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/...
allows only a single argument to the constructor to the underlying type. I'd suggest adding another CTOR with interface:
template<class Map, class... U> explicit any(const static_binding< Map > & binding, U &&... arg);
which is similar to:
explicit any(const binding< Concept > & binding, U &&... arg);
Then any constructor of the underlying could be used.
I think something like this is reasonable. I have to consider whether this is best approach, though. I don't consider this high priority, however, since the copy constructor should work most of the time. The STL got by just fine for years without emplace.
[too many any ctors]:
According to `grep -e ' any('`, there are more than 45 any constructors. That many makes it hard for the novice to know which one to use. The Design notes:
The solution is simple. Don't use the source. Use the documentation page for any, which only shows 9 distinct constructors.
http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/...
are some help, but those notes also mention ambiguities and user rules, which sound like indications of usability problems to me.
Why wouldn't the following ctors be sufficent to do all the current any constructors do (except for maybe requiring more typing and maybe more constructor calls)?
template < class... U > any ( static_binding<Map>const& , U&&... );//kind=binding constructor
template < class... U > any ( binding<Concept>const& , U&&... );//kind=dispatching constructor
template < class Concept2 , class Tag2 > any ( any<Concept2,Tag2>U&& , static_binding<Map>const& );//kind=converting constructor
template < class Concept2 , class Tag2 > any ( any<Concept2,Tag2>U&& u , binding<Concept2>const&b=binding_of(u) );//kind=converting constructor
Providing just these 4 constructors would improve the usabilty.
Why?
Of course, I'm probably missing something, and if so, explaining why the above would not work in the Design notes would be helpful.
I think it should be obvious what's missing: a) any(const any&); The copy constructor is not a template. b) template<class U> any(const U&); This is the most commonly used constructor besides the copy constructor. It would be very inconvenient if it didn't exist. c) any(); The default constructor creates an empty any. d) A default argument can't refer to a prior argument. Your fourth constructor has to be two separate constructors.
2. What is your evaluation of the implementation?
[in-source comments]: Very few in-source comments, as for example, the in the code:
http://steven_watanabe.users.sourceforge.net/type_erasure/boost/type_erasure...
there are no in-source comments. This lack of in-source comments made it very hard to understand the implementation. There is also no tests in the directory:
http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/...
which contain any string with 'normalize' in it; hence, I assume there are no unit tests for any class or function with normalize as part of its name. Such unit tests, hopefully, would have provided more information of the purpose of the code in */detail/normalize.hpp; hence, I'd recommend providing such tests in addition to more in-source comments.
The tests only cover the public interface. I'm not going to add specific tests of the implementation details.
3. What is your evaluation of the documentation?
Mostly good, but some documentation needs improvement. For example:
[vague:rebinding_any.html]:
This doc:
http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/...
Claims rebind_any<Any,T>::type:
returns any type corresponding to a placeholder.
However, it doesn't say what the Any in rebind_any<Any,T> may be, and if one assumes Any is a type_erasure::any<C,S> for some concept, C, and placeholder, S, then that description makes no sense because C does not contain any information about which actual type is matched to which placeholder.
Huh? As the documentation you quoted says, rebind_any returns a specialization of /any/. rebind_any<any<C, S>, T>::type is any<C, T>.
<snip>
from Steven, in the reply:
http://article.gmane.org/gmane.comp.lib.boost.devel/233067
did I finally conclude:
The placeholders in concepts do *not* stand for the bound types but instead for the any's containing those bound types.
That depends on the context. boost::type_erasure::call "unwraps" these any's.
Which is similar to the conclusion which I posted here:
http://article.gmane.org/gmane.comp.lib.boost.devel/233078
Since the 233078 post got no replies, I assume that conclusion is right. If so, then that should be made clear in the documentation (including tutorials). In addition, the following example code (and especially the comments), should reduce future confusion on this topic:
/* {***any_ctor_kinds.cpp*** */ <snip>
I find this code almost completely unreadable.
If that conclusion is wrong, then the docs need to be modified (I've no idea how) to clearly define "matching" as used in the any.html#id2445089-bb reference.
[incomplete:tuple.html]:
The doc:
http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/...
makes no mention of how the binding produced by this call are generated.
Already fixed. In Christ, Steven Watanabe

Steven Watanabe wrote:
The tests only cover the public interface. I'm not going to add specific tests of the implementation details.
You might want to re-consider this. I find the "implementation tests" very useful for isolating issues on compilers which are unavailable to me when looking at the test failure matrix. Robert Ramey

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Friday, August 03, 2012 7:40 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
Further to my enthusiastic welcome to print sequence example, I have extended this to other types, but come unstuck for std::map :-( I've created a map std::map<int, double> my_map; my_map.insert(std::make_pair(1, 9.9)); my_map.insert(std::make_pair(2, 8.8)); and made sure I can output the values using a forward iterator for (std::map<int, double>::iterator it = my_map.begin(); it != my_map.end(); ++it) { std::cout << *it << std::endl; } with an operator<< for pair (untidily in global namespace for the purpose of this example). template <typename K, typename T> std::ostream& operator<< (std::ostream& os, std::pair<K, T>& p) { /*! Output a pair of values. \details For example: "1.23 , 3.45". */ os << p.first << ", " << p.second; return os; } And I can echo the input as expected 1, 9.9000 2, 8.8000 but when I try to use the sequence printer p2.print(std::cout, my_map); the compiler (VC10) complains the there is no operator<< I:\boost-sandbox\type_erasure\boost/type_erasure/operators.hpp(422): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const std::pair<_Ty1,_Ty2>' (or there is no acceptable conversion) with [ _Ty1=const int, _Ty2=double ] (I've tried several combinations of const or not, const int or int, and pair<K, T> and <K, T>& so I can't see that this is a const issue or ref issue). What am I doing wrong? Paul PS I'm not sure I understand the base_and_derived and concept_interface structs and how they are used. Some explanation would be useful for the novice. --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

AMDG On 08/06/2012 02:55 AM, Paul A. Bristow wrote:
template <typename K, typename T> std::ostream& operator<< (std::ostream& os, std::pair<K, T>& p) { /*! Output a pair of values. \details For example: "1.23 , 3.45". */ os << p.first << ", " << p.second; return os; }
And I can echo the input as expected
1, 9.9000 2, 8.8000
but when I try to use the sequence printer
p2.print(std::cout, my_map);
the compiler (VC10) complains the there is no operator<<
Yep. It can't be found by ADL unless it's declared in namespace std, which is forbidden. You can solve this by specializing boost::type_erasure::ostreamable instead, In Christ, Steven Watanabe

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Monday, August 06, 2012 1:22 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/06/2012 02:55 AM, Paul A. Bristow wrote:
template <typename K, typename T> std::ostream& operator<< (std::ostream& os, std::pair<K, T>& p) { /*! Output a pair of values. \details For example: "1.23 , 3.45". */ os << p.first << ", " << p.second; return os; }
And I can echo the input as expected
1, 9.9000 2, 8.8000
but when I try to use the sequence printer
p2.print(std::cout, my_map);
the compiler (VC10) complains the there is no operator<<
Yep. It can't be found by ADL unless it's declared in namespace std, which is forbidden. You can solve this by specializing boost::type_erasure::ostreamable instead,
I've confirmed that it works in the forbidden namespace std, but despite some splinters from head scratching, I have concluded that this is not in my skill set :-( This specialization of ostreamable: template<> struct ostreamable<class Os, const std::pair<const int, double>& > { static void apply(Os& out, const std::pair<const int, double>& arg) { out << arg; // No operator<< of type 'Os' } }; still doesn't resolve the requirement. type_erasure_print_map.cpp(140): error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'Os' (or there is no acceptable conversion) type_erasure_print_map.cpp(86): could be 'std::ostream &boost::type_erasure::operator <<<const int,double>(std::ostream &,const std::pair<_Ty1,_Ty2> &)' with [ _Ty1=const int, _Ty2=double ] type_erasure_print_map.cpp(96): or 'std::ostream &boost::type_erasure::operator <<(std::ostream &,const std::pair<_Ty1,_Ty2> &)' with [ _Ty1=const int, _Ty2=double ] while trying to match the argument list '(Os, const std::pair<_Ty1,_Ty2>)' with [ _Ty1=const int, _Ty2=double ] (Of course I really want the pairs types to be templated for types T1, and T2, but I thought I'd try to make it simpler to start). What am I still doing wrong? Thanks. Paul PS a full (not-)working example attached. --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

AMDG On 08/07/2012 10:45 AM, Paul A. Bristow wrote:
This specialization of ostreamable:
template<> struct ostreamable<class Os, const std::pair<const int, double>& > { static void apply(Os& out, const std::pair<const int, double>& arg) { out << arg; // No operator<< of type 'Os' } };
still doesn't resolve the requirement.
This is an explicit specialization which uses a class called Os. I think you intended a partial specialization: template<class Os> struct ostreamable<Os, std::pair<const int, double> >;
type_erasure_print_map.cpp(140): error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'Os' (or there is no acceptable conversion)
In Christ, Steven Watanabe

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Tuesday, August 07, 2012 11:29 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
This is an explicit specialization which uses a class called Os. I think you intended a partial specialization:
template<class Os> struct ostreamable<Os, std::pair<const int, double> >;
I've placed this just before my int main(){...} namespace boost { namespace type_erasure { // Partial specialization of struct ostreamable: template<class Os> struct ostreamable<Os, std::pair<const int, double> >; } // namespace type_erasure } // namespace boost looks more promising but still fails inside the magic of type_erasure. type_erasure_print_map.cpp I:\boost-sandbox\type_erasure\boost/type_erasure/detail/get_signature.hpp(23): error C2027: use of undefined type 'boost::type_erasure::ostreamable<Os,T>' with [ Os=std::basic_ostream<char,std::char_traits<char>>, T=std::pair<const int,double> ] I:\boost-sandbox\type_erasure\boost/type_erasure/detail/get_signature.hpp(25) : see reference to class template instantiation 'boost::type_erasure::detail::get_signature<Concept>::nested' being compiled with [ Concept=boost::type_erasure::ostreamable<std::basic_ostream<char,std::char_traits<char>>,std::pair<c onst int,double>> ] I:\boost-sandbox\type_erasure\boost/type_erasure/detail/adapt_to_vtable.hpp(235) : see reference to class template instantiation 'boost::type_erasure::detail::get_signature<Concept>' being compiled with [ Concept=boost::type_erasure::ostreamable<std::basic_ostream<char,std::char_traits<char>>,std::pair<c onst int,double>> ] ... Full message in all its glory attached ;-) Suggestions? Thanks Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

AMDG On 08/08/2012 02:09 AM, Paul A. Bristow wrote:
namespace boost { namespace type_erasure {
// Partial specialization of struct ostreamable: template<class Os> struct ostreamable<Os, std::pair<const int, double> >;
} // namespace type_erasure } // namespace boost
looks more promising but still fails inside the magic of type_erasure.
You still need the definition. I only posted the declaration because the body of the specialization that you had looked okay. In Christ, Steven Watanabe

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Wednesday, August 08, 2012 3:29 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/08/2012 02:09 AM, Paul A. Bristow wrote:
namespace boost { namespace type_erasure {
// Partial specialization of struct ostreamable: template<class Os> struct ostreamable<Os, std::pair<const int, double> >;
} // namespace type_erasure } // namespace boost
looks more promising but still fails inside the magic of type_erasure.
You still need the definition. I only posted the declaration because the body of the specialization that you had looked okay.
Ah yes - of course. This now works fine (templated too) provided the function template <typename T1, typename T2> std::ostream& operator<< (std::ostream& os, const std::pair<T1, T2>& p) { ...} lives in namespace boost::type_erasure. But really I'd like it to live in my_detail namespace or it will be confusing for other uses outside type_erasure/any things. putting the operator<< for pair in namespace my_detail and using my_detail::operator<<; in namespace boost::type_erasure before the partial specialization of ostreamable seems to permit this. Even more than often, when using boost::type_erasure, namespace issues seem likely to be an unwelcome complication and source of puzzling behaviour :-( Perhaps some warnings for the unwary might be helpful. For one example, I was confused at first by having the same name like any and tuple in more than one namespace. Many thanks Paul PS I haven't found the docs on ostreamable Error 503 Service Unavailable Service Unavailable Guru Meditation: XID: 731432893 Varnish cache server No doubt a release will provide. ostreamable will, no doubt, be a very popular requirement. Examples will be invaluable, perhaps links to the \tests\test_stream.cpp (for example) might be a quick way of providing many more examples? PPS The error messages a dreadfully inscrutable :-( I've not even found the line number causing the problem in many cases. But perhaps that is inevitable? --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Paul A. Bristow Sent: Wednesday, August 08, 2012 5:40 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
I've checked that using an typedef any< mpl::vector < // List of concepts. typeid_<>, arithmetic<>, // Re-using another list of concepts. negatable<>, ostreamable<> > > arith_type; arith_type x(10); arith_type y(4); but find that while x = -y; works as expected, x = +y doesn't work. Of course the + is redundant, but I have used it for clarity. Should the unary plus be included for completeness? Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Thursday, August 09, 2012 3:52 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/09/2012 02:27 AM, Paul A. Bristow wrote:
Should the unary plus be included for completeness?
Sure. What should it be called?
plusable perhaps? I can't think of any better. Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

On Thu, Aug 9, 2012 at 4:44 PM, Paul A. Bristow <pbristow@hetp.u-net.com>wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto: boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Thursday, August 09, 2012 3:52 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/09/2012 02:27 AM, Paul A. Bristow wrote:
Should the unary plus be included for completeness?
Sure. What should it be called?
plusable
perhaps?
I can't think of any better.
unaryaddable maybe? - Rob.

on Thu Aug 09 2012, Robert Jones <robertgbjones-AT-gmail.com> wrote:
On Thu, Aug 9, 2012 at 4:44 PM, Paul A. Bristow <pbristow@hetp.u-net.com>wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto: boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Thursday, August 09, 2012 3:52 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/09/2012 02:27 AM, Paul A. Bristow wrote:
Should the unary plus be included for completeness?
Sure. What should it be called?
plusable
perhaps?
I can't think of any better.
unaryaddable maybe?
I don't think unary plus can be considered an addition. -- Dave Abrahams BoostPro Computing Software Development Training http://www.boostpro.com Clang/LLVM/EDG Compilers C++ Boost

Dave Abrahams <dave@boostpro.com> writes:
on Thu Aug 09 2012, Robert Jones <robertgbjones-AT-gmail.com> wrote:
On Thu, Aug 9, 2012 at 4:44 PM, Paul A. Bristow <pbristow@hetp.u-net.com>wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto: boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Thursday, August 09, 2012 3:52 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/09/2012 02:27 AM, Paul A. Bristow wrote:
Should the unary plus be included for completeness?
Sure. What should it be called?
plusable
perhaps?
I can't think of any better.
unaryaddable maybe?
I don't think unary plus can be considered an addition.
Posatable (complement of negatable) ;) Alex -- Swish - Easy SFTP for Windows Explorer

On Sun, Aug 19, 2012 at 3:48 AM, Alexander Lamaison <awl03@doc.ic.ac.uk>wrote:
Dave Abrahams <dave@boostpro.com> writes:
on Thu Aug 09 2012, Robert Jones <robertgbjones-AT-gmail.com> wrote:
On Thu, Aug 9, 2012 at 4:44 PM, Paul A. Bristow <pbristow@hetp.u-net.com>wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto: boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Thursday, August 09, 2012 3:52 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/09/2012 02:27 AM, Paul A. Bristow wrote:
Should the unary plus be included for completeness?
Sure. What should it be called?
plusable
perhaps?
I can't think of any better.
unaryaddable maybe?
I don't think unary plus can be considered an addition.
Posatable (complement of negatable) ;)
I like affirm as a name for unary operator +, because it's an antonym of negate, it can be made into other parts of speech similarly to negate, and because I think it conveys the general redundancy of using unary operator +. If you think of unary operator + as the affirmation operator, then you can use affirmable here. Nick

On 8/20/2012 10:39 AM, Nicholas Howe wrote:
On Sun, Aug 19, 2012 at 3:48 AM, Alexander Lamaison <awl03@doc.ic.ac.uk>wrote:
Dave Abrahams <dave@boostpro.com> writes:
on Thu Aug 09 2012, Robert Jones <robertgbjones-AT-gmail.com> wrote:
On Thu, Aug 9, 2012 at 4:44 PM, Paul A. Bristow <pbristow@hetp.u-net.com>wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto: boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Thursday, August 09, 2012 3:52 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/09/2012 02:27 AM, Paul A. Bristow wrote: > > Should the unary plus be included for completeness? >
Sure. What should it be called?
plusable
perhaps?
I can't think of any better.
unaryaddable maybe?
I don't think unary plus can be considered an addition.
Posatable (complement of negatable) ;)
I like affirm as a name for unary operator +, because it's an antonym of negate, it can be made into other parts of speech similarly to negate, and because I think it conveys the general redundancy of using unary operator +. If you think of unary operator + as the affirmation operator, then you can use affirmable here.
For an early version of Proto, I used "posit" (v. Assume as a fact; put forward as a basis of argument.) as the name for the unary plus operator for many of the same reasons you cite above. There was a hew and a cry during Proto's review, and I had to change it to unary_plus. Just another data point. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 08/20/12 12:46, Eric Niebler wrote:
On 8/20/2012 10:39 AM, Nicholas Howe wrote:
On Sun, Aug 19, 2012 at 3:48 AM, Alexander Lamaison <awl03@doc.ic.ac.uk>wrote:
Dave Abrahams <dave@boostpro.com> writes:
on Thu Aug 09 2012, Robert Jones <robertgbjones-AT-gmail.com> wrote:
On Thu, Aug 9, 2012 at 4:44 PM, Paul A. Bristow <pbristow@hetp.u-net.com>wrote:
> -----Original Message----- > From: boost-bounces@lists.boost.org [mailto: boost-bounces@lists.boost.org] On Behalf Of Steven > Watanabe > Sent: Thursday, August 09, 2012 3:52 PM > To: boost@lists.boost.org > Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012) > > AMDG > > On 08/09/2012 02:27 AM, Paul A. Bristow wrote: >> >> Should the unary plus be included for completeness? >> > > Sure. What should it be called?
plusable
perhaps?
I can't think of any better.
unaryaddable maybe?
I don't think unary plus can be considered an addition.
Posatable (complement of negatable) ;)
I like affirm as a name for unary operator +, because it's an antonym of negate, it can be made into other parts of speech similarly to negate, and because I think it conveys the general redundancy of using unary operator +. If you think of unary operator + as the affirmation operator, then you can use affirmable here.
For an early version of Proto, I used "posit" (v. Assume as a fact; put forward as a basis of argument.) as the name for the unary plus operator for many of the same reasons you cite above. There was a hew and a cry during Proto's review, and I had to change it to unary_plus.
Just another data point.
I like unary_plus because it's so simple and immediately conveys what it means. One may object by saying plus is a binary operation, and prefixing it with unary is a contradiction, but then so is +1. But then that would suggest negatable be renamed to unary_minus. -regards, Larry

On Mon, Aug 20, 2012 at 10:56 AM, Larry Evans <cppljevans@suddenlink.net> wrote:
On 08/20/12 12:46, Eric Niebler wrote:
On 8/20/2012 10:39 AM, Nicholas Howe wrote:
On Sun, Aug 19, 2012 at 3:48 AM, Alexander Lamaison <awl03@doc.ic.ac.uk>wrote:
Dave Abrahams <dave@boostpro.com> writes:
on Thu Aug 09 2012, Robert Jones <robertgbjones-AT-gmail.com> wrote:
On Thu, Aug 9, 2012 at 4:44 PM, Paul A. Bristow <pbristow@hetp.u-net.com>wrote:
>> -----Original Message----- >> From: boost-bounces@lists.boost.org [mailto: > boost-bounces@lists.boost.org] On Behalf Of Steven >> Watanabe >> Sent: Thursday, August 09, 2012 3:52 PM >> To: boost@lists.boost.org >> Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012) >> >> AMDG >> >> On 08/09/2012 02:27 AM, Paul A. Bristow wrote: >>> >>> Should the unary plus be included for completeness? >>> >> >> Sure. What should it be called? > > plusable > > perhaps? > > I can't think of any better. > > unaryaddable maybe?
I don't think unary plus can be considered an addition.
Posatable (complement of negatable) ;)
I like affirm as a name for unary operator +, because it's an antonym of negate, it can be made into other parts of speech similarly to negate, and because I think it conveys the general redundancy of using unary operator +. If you think of unary operator + as the affirmation operator, then you can use affirmable here.
For an early version of Proto, I used "posit" (v. Assume as a fact; put forward as a basis of argument.) as the name for the unary plus operator for many of the same reasons you cite above. There was a hew and a cry during Proto's review, and I had to change it to unary_plus.
Just another data point.
I like unary_plus because it's so simple and immediately conveys what it means. One may object by saying plus is a binary operation, and prefixing it with unary is a contradiction, but then so is +1. But then that would suggest negatable be renamed to unary_minus.
The +a operator is called "unary plus" here http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Arithmetic_operators so /maybe/ unary_plusable... HTH, --Lorenzo

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Wednesday, August 08, 2012 3:29 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
namespace boost { namespace type_erasure { template <typename T1, typename T2> std::ostream& operator<< (std::ostream& os, const std::pair<T1, T2>& p) { /*! Output a pair of values with space as delimiter. \details For example: "1.23 3.45". */ os << p.first << " " << p.second; return os; } // std::ostream& operator<< (std::ostream& os, const std::pair<T1, T2>& p) // Partial specialization of struct ostreamable for pair<T1, T2>: template<class Os, typename T1, typename T2> struct ostreamable<Os, std::pair<T1, T2> > { static void apply(Os& out, const std::pair<T1, T2>& arg) { out << arg; } }; } // namespace type_erasure } // namespace boost Works nicely for anything needing std::pair like map. Followers of this thread may also be amused to see my fumblings with type_erasure (attached) adding a few more bells and whistles and using with lots of types of things (including User defined types) in various containers. I can see lots of neat applications just printing things in containers. Paul PS I note in fiddling with cosmetic details that boost::tuple only provides a char option for std::cout << set_open('[') << set_delimiter('_') << set_close(']') << std::endl; this prevents, for example ", " (comma and space) as a delimiter. Can anyone remember a good reason why a std::string is not also provided?

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Wednesday, August 08, 2012 3:29 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
I've wanted to add control of the column width. virtual void do_print( ostream_type os, iterator_type first, iterator_type last) const { if(first != last) { os << *first; ++first; for(; first != last; ++first) { os << separator.c_str() << *first; } } I expected to be able to add os.width(20); before os << separator.c_str(); but that doesn't work. j:\cpp\misc\type_erasure_lister\./type_erasure_lister.hpp(219): error C2039: 'width' : is not a member of 'boost::type_erasure::any<Concept,T>' with [ Concept=abstract_printer::requirements, T=_os & ] Is there some requirement that I need to add to os to permit this? I stabbed at something like callable<int(int)> but that doesn't help. Thanks Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

AMDG On 08/15/2012 09:06 AM, Paul A. Bristow wrote:
I've wanted to add control of the column width.
<snip>
I expected to be able to add
os.width(20);
before
os << separator.c_str();
but that doesn't work.
<snip>
You should be able to use: static_cast<std::ios_base&>(os).width(20); In Christ, Steven Watanabe

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: Wednesday, August 15, 2012 5:43 PM To: boost@lists.boost.org Subject: Re: [boost] [type_erasure] Review started (July 18-27, 2012)
AMDG
On 08/15/2012 09:06 AM, Paul A. Bristow wrote:
I've wanted to add control of the column width.
<snip>
I expected to be able to add
os.width(20);
before
os << separator.c_str();
but that doesn't work.
<snip>
You should be able to use: static_cast<std::ios_base&>(os).width(20);
Correct! Thanks Paul

On 08/03/12 13:39, Steven Watanabe wrote:
AMDG
On 08/02/2012 12:29 PM, Larry Evans wrote:
On 07/18/12 00:13, Lorenzo Caminiti wrote:
Hello all,
*** The review of Steven Watanabe's proposed Boost.TypeErasure library begins on July 18, 2012 and ends on July 27, 2012. *** [snip] Should type_erasure be accepted into Boost?
Answer: No, not yet. Why(in order of importance):
1) any<C,T>::any(U&, static_binding<Map>&) bug
The bug reported here: http://article.gmane.org/gmane.comp.lib.boost.devel/233101 should be resolved.
The bug is just too dangerous for the resolution to be delayed.
I added a static assert.
Then I withdraw that objection :)
<snip>
My review:
1. What is your evaluation of the design?
Good, except for:
[need variadic static_binding ctor]:
The any CTOR:
template<class U, class Map> any(U & arg, const static_binding< Map > & binding);
documented here:
http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/...
allows only a single argument to the constructor to the underlying type. I'd suggest adding another CTOR with interface:
template<class Map, class... U> explicit any(const static_binding< Map > & binding, U &&...
arg);
which is similar to:
explicit any(const binding< Concept > & binding, U &&... arg);
Then any constructor of the underlying could be used.
I think something like this is reasonable. I have to consider whether this is best approach, though. I don't consider this high priority, however, since the copy constructor should work most of the time. The STL got by just fine for years without emplace.
[too many any ctors]:
[snip]
Why wouldn't the following ctors be sufficent to do all the current any constructors do (except for maybe requiring more typing and maybe more constructor calls)?
template < class... U > any ( static_binding<Map>const& , U&&... );//kind=binding constructor
template < class... U > any ( binding<Concept>const& , U&&... );//kind=dispatching constructor
template < class Concept2 , class Tag2 > any ( any<Concept2,Tag2>U&& , static_binding<Map>const& );//kind=converting constructor
template < class Concept2 , class Tag2 > any ( any<Concept2,Tag2>U&& u , binding<Concept2>const&b=binding_of(u) );//kind=converting constructor
Providing just these 4 constructors would improve the usabilty.
Why?
Someone trying to understand the source would have less to understand if all the other CTOR's were simply defined in terms of these, more basic CTORS, as shown in the refactoring below. This defining of one CTOR in terms of other, more basic CTOR's, makes the source easier to understand, a viewpoint expressed by: Refactoring is a good thing because complex expressions are typically built from simpler, more grokable components. from: http://c2.com/cgi/wiki?WhatIsRefactoring Also, putting a description of this in the docs would make understanding how to use the library easier. The mpl docs, which I've found very usable, do something similar where they describe one metafunction in terms of other, more basic metafunctions. For example: http://www.boost.org/doc/libs/1_50_0/libs/mpl/doc/refmanual/fold.html contains: Semantics: Equivalent to typedef iter_fold< s , state , apply_wrap2< lambda<op>::type, _1, deref<_2> > >::type t;
Of course, I'm probably missing something, and if so, explaining why the above would not work in the Design notes would be helpful.
I think it should be obvious what's missing:
a) any(const any&); The copy constructor is not a template. b) template<class U> any(const U&); This is the most commonly used constructor besides the copy constructor. It would be very inconvenient if it didn't exist. c) any(); The default constructor creates an empty any. d) A default argument can't refer to a prior argument. Your fourth constructor has to be two separate constructors.
Of course you're right that the 4 basic CTOR's don't include the one's you mention. I should have been more explicit about the purpose of those CTOR's. I was trying to say that all the CTORs could be defined in terms of just these 4 basic CTOR's, which is a just a refactoring. http://en.wikipedia.org/wiki/Code_refactoring I sort of hinted at this refactoring purpose, with the following from my review: (except for maybe requiring more typing and maybe more constructor calls)? I realize now that hint was not obvious. Sorry. The refactoring below makes this explicit. In addition, I really should have actually tried to refactor all the CTOR's just using these basic, let's call them any_core, CTOR's. These basic CTOR's, after renaming, would then be as shown next. (The CTOR's are prefixed with "labels", such as //[c1], to make referencing them easier later.): //[c1]: template < class... U > any_core ( static_binding<Map>const& , U&&... );//kind=binding constructor //[c2] template < class... U > any_core ( binding<Concept>const& , U&&... );//kind=dispatching constructor //[c3] template < class Concept2 , class Tag2 > any_core ( any_core<Concept2,Tag2>U&& , static_binding<Map>const& );//kind=converting constructor //[c4] template < class Concept2 , class Tag2 > any_core ( any_core<Concept2,Tag2>U&& u , binding<Concept2>const&b );//kind=converting constructor Basically, this refactoring would: 1) Use any_core<,> instead of compute_bases<...> as the supertype of the refactored any. 2) Use the current_compute_base<...> as the supertype of any_core<,>. Then the missing CTOR's, which you enumerated in your a)...d) list above, would use any_core as shown in this refactored 1. ... 9. list The 1. ... 9. list corresponds to the nine CTOR's listed in the doc: http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/... and this was done (instead of using the a)...d) CTOR list in your reply ) to assure I don't miss anything this time. 1. any(); any() : any_core<Concept,T> ( make_binding < mpl::map < > >() )//[c1] {} 2. template<typename U> explicit any(const U & data); template<typename U> explicit any(const U & data) : any_core<Concept,T> ( make_binding < mpl::map < mpl::pair<T,U> > >() , data )//[c1] {} 3. template<typename U, typename Map> any(const U & data, const static_binding< Map > & binding); template<typename U, typename Map> any(const U & data, const static_binding< Map > & binding) : any_core<Concept,T> ( binding , data )//[c1] {} 4. any(const any & other); any(const any & other) : any_core<Concept,T> ( binding_of(other) , other )//[c2] {} 5. template<typename Concept2, typename Tag2> any(const any< Concept2, Tag2 > & other); any(const any< Concept2, Tag2 > & other) : any_core<Concept,T> ( binding_of(other) , other )//[c2] {} 6. template<typename Concept2, typename Tag2, typename Map> any(const any< Concept2, Tag2 > & other, const static_binding< Map > & binding); any ( const any< Concept2, Tag2 > & other , const static_binding< Map > & binding ) : any_core<Concept,T> ( other , binding )//[c3] {} 7. template<typename Concept2, typename Tag2> any(const any< Concept2, Tag2 > & other, const binding< Concept > & binding); any ( const any< Concept2, Tag2 > & other , const binding< Concept > & binding ) : any_core<Concept,T> ( other , binding ) {}//[c4] 8. template<class... U> explicit any(U &&... arg); explicit any(U &&... arg) : any_core<Concept,T> ( _boost_type_erasure_extract_table ( decltype(this->_boost_type_erasure_deduce_constructor(arg...)) , arg... )//This expression has type, binding<Concept>const& , arg... )//[c2] {} 9. template<class... U> explicit any(const binding< Concept > & binding, U &&... arg); explicit any(const binding< Concept > & binding, U &&... arg); : any_core<Concept,T> ( binding , arg... )//[c2] {} NOTE: this has not been coded to actually test to see if it works; hence, the above may be missing something and not even compile. The 'core' components, any_core, closely reflect the 3 kinds of constructors you mention in design.html#boost_typeerasure.design.constructors; hence, I hope the advantage of such refactoring is more obvious to you. Another viewpoint is that the 9 any's are "shorthand" for more expressions and or statements using just any_core. Since you described the meaning of tuple using somewhat analogous "shorthand" here: http://article.gmane.org/gmane.comp.lib.boost.devel/232973 I'm hoping that this other viewpoint further convinces you. [snip]
3. What is your evaluation of the documentation?
Mostly good, but some documentation needs improvement. For example:
[vague:rebinding_any.html]:
This doc:
http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/...
Claims rebind_any<Any,T>::type:
returns any type corresponding to a placeholder.
However, it doesn't say what the Any in rebind_any<Any,T> may be, and if one assumes Any is a type_erasure::any<C,S> for some concept, C, and placeholder, S, then that description makes no sense because C does not contain any information about which actual type is matched to which placeholder.
Huh? Initially, I thought:
returns any type corresponding to a placeholder. meant rebind_any returns the underlying type corresponding to the placeholder. IOW, the type: mpl::at<Map,T>::type where Map was the template argument to the any CTOR: template<typename U, typename Map> any(U & arg, const static_binding< Map > & binding); However, since rebind_any doesn't use any instance of a type_erasure::any, there's know way it know what Map is. I had to figure out what the doc really meant, and the one that made sense was: returns any<C,T> where the Any argument to rebind_any is any<C,S> for some placeholder, S.
As the documentation you quoted says, rebind_any returns a specialization of /any/. rebind_any<any<C, S>, T>::type is any<C,T>.
AFAICT, the documentation quoted was from: http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/... which made no mention of any<C,T>. There was a mention of any<C,T> here: http://article.gmane.org/gmane.comp.lib.boost.devel/233015 which contained: Hmmm, do you mean the return type(i.e. rebind_any<any<C,S>,T>::type) is any<C,T>? which is an earlier version of what I'm suggesting above as a replacement for the existing: returns any type corresponding to a placeholder. Since you referred to that quoted document, I assume you're agreeing that the rebind_any documentation could be improved using something like the suggestion in that quoted document. Is that right?
<snip>
from Steven, in the reply:
http://article.gmane.org/gmane.comp.lib.boost.devel/233067
did I finally conclude:
The placeholders in concepts do *not* stand for the bound types but instead for the any's containing those bound types.
That depends on the context.
The part of my reply that was <snip>'ed included: ----snipped part---- [vague:any<C,T>::any(U&, binding<C>const&)]: The ref doc for this: http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/... ----snipped part---- So, obviously, the relevant context was the documentation for: explicit any(const binding< Concept > & binding, U &&... arg); ( and just as obviously, my label: [vague:any<C,T>::any(U&, binding<C>const&)] should have been: [vatgue:any(const binding< Concept > & binding, U &&... arg)] Sorry. ) And in that context, the above conclusion is right? In addition, the 'depends on context' is the crux of the problem. If there had been documentation on what a placeholder in a particular context, then there would have been no problem. And just to be sure, some accompanying examples to cement the meaning would be most helpful.
boost::type_erasure::call "unwraps" these any's.
Yes, I figured as much; although I certainly don't know how.
[snip]
In addition, the following example code (and especially the comments), should reduce future confusion on this topic:
/* {***any_ctor_kinds.cpp*** */ <snip>
I find this code almost completely unreadable.
The attached file: any_ctor_reformatted_kinds.cpp is a reformatting of the code in a form as close as I could make to the same way you format your code while still minimizing the code enclosed by the #if...#endif's. Hopefully, the attached is more readable.
If that conclusion is wrong, then the docs need to be modified (I've no idea how) to clearly define "matching" as used in the any.html#id2445089-bb reference.
[incomplete:tuple.html]:
The doc:
http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/...
makes no mention of how the binding produced by this call are generated.
Already fixed.
I just looked at the file and I don't see a simple and explicit description of how the bindings are produced. Currently(August 5, 2012), it contains: ---cut here--- Description tuple is a Boost.Fusion Random Access Sequence containing anys. Concept is interpreted in the same way as for any. The remaining arguments must be (possibly const and/or reference qualified) placeholders. tuple public construct/copy/destruct 1. template<class... U> explicit tuple(U &&... args); Constructs a tuple. Each element of args will be used to initialize the corresponding member. ---cut here--- Which is still a vague explanation. The one posted in my review is at least a little more explicit about how the binding are produced. -regards, Larry

There was a typo on any_core constructor with label //[c4]. On 08/07/12 15:04, Larry Evans wrote: [snip]
In addition, I really should have actually tried to refactor all the CTOR's just using these basic, let's call them any_core, CTOR's. These basic CTOR's, after renaming, would then be as shown next. (The CTOR's are prefixed with "labels", such as //[c1], to make referencing them easier later.): [snip] //[c4] template < class Concept2 , class Tag2 > any_core ( any_core<Concept2,Tag2>U&& u , binding<Concept2>const&b The above line should be: , binding<Concept>const& b );//kind=converting constructor
[snip] -Larry
participants (10)
-
Alexander Lamaison
-
Dave Abrahams
-
Eric Niebler
-
Larry Evans
-
Lorenzo Caminiti
-
Nicholas Howe
-
Paul A. Bristow
-
Robert Jones
-
Robert Ramey
-
Steven Watanabe