Boost logo

Boost :

Subject: Re: [boost] [type_traits][function_types] Discard param const qualification, bug or feature?
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2013-09-26 06:02:12


On Thu, Sep 26, 2013 at 1:28 PM, Rob Stewart <robertstewart_at_[hidden]>wrote:

> On Sep 25, 2013, at 5:09 AM, Andrey Semashev <andrey.semashev_at_[hidden]>
> wrote:
>
> > I have to say that while these rules are logical and understandable when
> > explained, types of function arguments are a constant source of
> confusion.
>
> There are many things about C++ that are contrary to someone's intuition.
> That parameter declaration is no different than the following variable:
>
> int const i;
>
> When used with either of the forms of f(), above, does i work any
> differently than j, below?
>
> int j;
>
> They work alike with either f(), because the int is copied. The difference
> is whether you can change the int after initialization. The parameters are
> no different.
>

Sure, they work the same, from the caller's perspective. But is that a
reason to cheat with the type system?

void foo(int);
void bar(const int);

typeid(&foo) == typeid(&bar); // why?

My point was that despite the same behavior on the caller's side, the
functions have different signatures, and I don't see why there was a
_necessity_ to force the compiler to drop cv-qualifiers from the function
argument types. In other words, it makes the language more complicated for
no apparent reason.

> > But C++11 brought us
> > rvalue references, and the following:
> >
> > foo(int&& n)
> > {
> > // n is _not_ rvalue reference here
> > }
> >
> > I understand the rationale for this, and it seems the right thing. But
> once in a while, when yet another fellow developer asks me why is that so,
> I wonder if it would be better if the standard was more straight-forward in
> > this part.
>
> The issue comes down to one of consequences. If n were still an rvalue,
> within foo(), even when referenced by name, what problems will that cause?
>

AFAIR, the motivating example was something like this:

  void bar(int&& n); // moves from n

  void foo(int&& n)
  {
    bar(n);
    bar(n); // moves from a moved-from object
    ++n; // uses a moved-from object
  }

This can be a real gotcha, I admit. But just as well as this:

  class my_class
  {
    vector<int> vec;

  public:
    my_class(vector<int>&& v) : vec(v) // copies the vector, instead of
moving
    {
    }
  };

This latter mistake is usually less critical, but for that reason it is
also more often made and left unnoticed.


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