$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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.