Boost logo

Boost :

Subject: Re: [boost] boost and vendor's TR1 implementations
From: Sergey Sadovnikov (flex_ferrum_at_[hidden])
Date: 2008-11-12 19:30:16


Hello, David.

Wednesday, November 12, 2008 at 11:00:24 PM you wrote:

>> Absolutely right, but...
>> Let's see an example. Just get the one of the boost test cases
>> (http://www.boost.org/doc/libs/1_37_0/libs/function/test/lambda_test.cpp)and try to compile with gcc 4.3.2:

DA> I would never claim that all the Boost test cases follow a good
DA> practice.
:) But the same code is present in the documentation. For example,
boost::assign
(http://www.boost.org/doc/libs/1_37_0/libs/assign/doc/index.html), or boost::spirit
(http://www.boost.org/doc/libs/1_37_0/libs/spirit/classic/example/fundamental/number_list.cpp),
 or boost::asio
 (http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/example/porthopper/client.cpp).
Developers follow this documentation and produce potentially
uncompilable code... Some kind of delayed-action mine. I agree what
developer has to use his own head. BTW such developer suppose what boosters knows
what they do and their code is a high-quality code. Developer is
wrong? :)

>> I mean that code which is conform to the some boost examples or other
>> *same* guidelines which explicitly or implicitly expose both 'boost' and
>> 'std' namespaces into global or local scope could become
>> automatically uncompilable...

DA> Yes, really, I understood the problem the first time you described it.
DA> It's very bad, for people with code like that. I argued once with Herb
DA> that using directives are a bad idea in general, and he said, "if your
DA> code breaks, you just add qualification and fix it." So I can't account
DA> for any programming guidelines he's given that sanction using
DA> directives. In the few cases where it's okay, you have tight control
DA> over the future evolution of each namespace involved, so you know that
DA> collisions won't happen.
In other words you are offering to developers to make a choose between
simpler code and unambiguous code. It is clear what second choice is
preferable. But both boost and STL main goal is to make code and
coding process simpler. Isn't it? And what we will have? At least:
1. Ambiguous names in the 'polluted' global scope. Ok, it is a bad
practice and let's forget about it.
2. Compatible (or non-compatible?) boost-conformant and C++0x-conformant
code. Could developer simply cast boost::shared_ptr to std::shared_ptr
and back? Could developers use std::bind everywhere where boost::bind
is suitable? What about tuples, functions, etc.?
3. Quite complex form of std binders. Because we all agreed what std
and boost namespaces will not exposed into global scope, developer have to
write (for example):
std::for_each(v.begin(), v.end(), std::bind(&foo,
std::placeholders::_1);
If developer will want to simplify his life and will write somewhere:

using namespace std::placeholders;

... He will take a dial with boost::bind placeholders which are
already in the global scope... And he couldn't
avoid this ambiguous because of some other boost headers include
boost/bind.hpp directly (thread, statechart, python, multi_index,
algorithm and other).
4. Some amount of boost code relay on the boost implementation of the new
TR1 facilities. Is this code will work with corresponding
C++0x-conformant facilities? Let's try:

-----------------------------------------------------------------------
#include <iostream>
#include <map>
#include <algorithm>
#include <iterator>
#include <tr1/functional>

#include <boost/iterator/transform_iterator.hpp>

int main(int, char*[])
{
        std::map<int, int> test_map;

        test_map[0] = 10;
        test_map[1] = 5;
        test_map[5] = 8;
        test_map[3] = 20;

        
        typedef std::map<int,int>::value_type vt;

        std::copy(boost::make_transform_iterator(test_map.begin(), std::tr1::bind(&vt::second, std::tr1::placeholders::_1)),
                  boost::make_transform_iterator(test_map.end(), std::tr1::bind(&vt::second, std::tr1::placeholders::_1)),
                  std::ostream_iterator<int>(std::cout, "\n"));
}
-----------------------------------------------------------------------

This code can't be compiled both with g++ 4.3.2 and VS2008 SP1. Both
compilers "complain" on the "result_type" absence in the binder passed
to the transform iterator. I suppose what this is the issue in the
vendor's TR1 implementation but I (as a C++ developer) have to avoid
such cases and have to make my code more complex. But what about
another code? Today it isn't so scary because of TR1 implementations are mostly experimental and almost all
libraries relay on the boost facilities. But what we will have in the
future when some libraries will relay on the boost, other relay on
the STL and developer will have to use both ones for some reason? In one
piece of code they have to write something like "std::bind(...,
std::placeholders::_1)", in other piece "boost::bind(..., ::_1)",
somewhere "boost::shared_ptr", somewhere else "std::shared_ptr"... A
so on and on and on and on... And always keep in mind which version of
class they have to use in certain place... And nothing about compatibility of this
classes... Or am I wrong, and just dramatizing the situation, and
"We emphasize libraries that *work well with the C++ Standard Library*.
Boost libraries are intended to be widely useful, and usable across a broad spectrum of applications."
slogan still true? TR1 will become the part of the C++ Standard Library in the
next year, I suppose. :)

-- 
Best Regards,
 Sergey                          mailto:flex_ferrum_at_[hidden]

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