Boost logo

Boost :

From: Beman Dawes (bdawes_at_[hidden])
Date: 2002-08-01 07:33:24


At 04:08 AM 8/1/2002, Mattias Flodin wrote:

>I had a quick look at the filesystem library headers and noticed this
>comment in path.hpp:
>
>// Rationale for returns of "const path" instead of "path"; see
>// Scott Meyers, EC++, Item 21.
>
>Now, that item says that operator+() and others returning a const object
>is "The Right Thing To Do" because it prevents you from doing silliness
>such as
>
> (a + b) = c
>
>which is not allowed on native types and therefore, by extension, should
>not be allowed on user-defined types.
>
>This item is about operators. Class path returns const std::string from
>leaf() and const path from branch(), both of which are ordinary member
>functions not operators, so there is no correlation with native types
>here to begin with.

The worry is expressions like:

    path p1, p2;
    ...
    p1.branch() = p2; // doesn't do what it looks like it does

>I was going to complain about how this somewhat arbitrary restriction on
>what the user can do with his temporary objects just gives the user a
>hard time, without any benefits. But since I can't find any examples of
>prevented usage that isn't obscure, I suppose I can live with it.

I'm not wedded to the const value returns. It isn't something I've
traditionally done, but as I've become more aware of the issue it seems
like a useful practice. Before changing to non-const, I'd like to see some
really useful expressions that would be prevented by the const. Otherwise
the increased safety wins.

>What I've been meaning to ask, after this somewhat wordy post, are two
>things. First, path::begin() returns a mutable iterator. Shouldn't it be
>returning a const iterator, for the same reasons as above? Same thing
>goes for path::end().

I'm not quite sure what you mean here. The iterator reference type is
supposed to be "const std::string &", and the iterator_adaptor is coded
accordingly:

       typedef boost::iterator_adaptor<
         detail::path_itr_imp,
         boost::default_iterator_policies,
         const std::string,
         const std::string &,
         const std::string *,
         std::bidirectional_iterator_tag,
         std::ptrdiff_t
> iterator;

Just to be sure I understand iterator_adaptor<> correctly, I tried:

    path p2( "foo/bar" );
    *p2.begin() = "should-fail"; // error!

This did result in the expected error message about trying to assign to a
const string.

>Secondly, if it is really a good idea to return const objects for all
>functions and not just operators, should that be a coding policy for
>boost? Should we look over the other libraries and make sure they all
>return const objects?

See Daniel Frey's post. I don't want to try to pass myself off as an
expert in something I'm not really an expert in, but my take is we should
at the least be thinking about that. Why don't you take a look at some
other Boost libraries, and see if you can spot questionable returns by
value?

By the way, in researching your questions I spotted several minor docs
mistakes in path.htm where the docs didn't agree with the header, and have
corrected them.

--Beman


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