Topic: Generics and member function types [N2855 and old std::MoveConstructible]


Author: "Niels Dekker - no reply address" <invalid@this.is.invalid>
Date: Sun, 14 Jun 2009 20:09:14 CST
Raw View
> // C++0x:
> class vector
> {
> public:
>   value_type & at(size_type) &;
>   value_type && at(size_type) &&;
>   value_type const& at(size_type) const&;
> };

Please note that the declarations of the at(size_type) member functions in
this example of mine differ from the ones of std::vector, from the C++0x
Working Draft, www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2857.pdf
The current C++0x std::vector::at(size_type) functions don't have
ref-qualifiers. As a consequence, when you call std::vector::at on an
rvalue, it returns an lvalue reference.  (As it did in C++03.)


> // Hypothetical C++ inc. your "qualifiers" keyword:
> class vector
> {
> public:
>   template <qualifiers CV>
>   value_type CV at(size_type) CV;
> };

That would look very nice to me  :-)


Kind regards, Niels



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: SG <s.gesemann@gmail.com>
Date: Sun, 14 Jun 2009 20:08:43 CST
Raw View
On 14 Jun., 15:25, "Niels Dekker - no reply address"
<inva...@this.is.invalid> wrote:
> "SG" <s.gesemann> wrote:
> > It already bugs me that you can't write std::memfun in a
> > truly generic way
>
> I assume you mean std::mem_fun. (Mind the underscore!)
>
> > but you have to consider four cases for different
> > const/volatile versions of member functions.
>
> That's a pity, indeed.
>
> > IMHO, we ought to be able to handle things like
> > noexcept, const, volatile without writing different
> > versions for every special case. One approach would
> > be to
>
> >   o) extend the template system with a new kind of
> >      parameter for cv qualifiers
>
> Don't forget the ref-qualifiers!

Right. They probably make things even more complicated. A tool like
std::mem_fun (or the future std::bind) should support all combinations
of noexpect, const, volatile and lref for member functions. But the
number of those combinations is 16 --- sixteen!

> >   o) make noexcept parameterisable

In the example below I used noexcept with a boolean parameter. Its
default value could be true so that

 void foo(); // is equivalent to
 noexcept<false> void foo();

 noexcept void bar(); // is equivalent to
 noexcept<true> void bar();

> > --------8<--------[ BEGIN hypothetical C++ ]--------8<--------
>
> >   template< bool NoExcept, typename Ret, class Clz,
> >     qualifiers CV, typename ... Parms >
> >   class memfun_t
> >   {
> >   public:
> >     typedef noexcept<NoExcept> Ret (Clz::*pmf_t)(Parms...) CV;
> >     typedef Clz CV* objptr_t;

In case "CV" includes a ref qualifier this won't work.

>
> >     memfun_t(pmf_t pmf) : pmf(pmf) {}
>
> >     noexcept<NoExcept>
> >     Ret operator()(objptr_t po, P... params) const
> >     {
> >       return (*po)(std::forward<P>(params)...);

Of course, this should have been

 return (po->*pmf)(std::forward<P>(params)...);

> >     }
> >   private:
> >     pmf_t pmf;
> >   };
>
> >   template< bool NoExcept, typename Ret, class Clz,
> >     qualifiers CV, typename ... Parms >
> >   memfun_t<NoExcept,Ret,Clz,CV,Params...>
> >   memfun( noexcept<NoExcept> Ret (Clz::*pmf)(Params...) CV )
> >   {
> >     return memfun_t<NoExcept,Ret,Clz,CV,Params...>(pmf);
> >   }
>
> > --------8<--------[ END hypothetical C++ ]--------8<--------
>
> I think such a language extension would be very useful. Especially if it
> could also help in a different context, having to write overloads for const,
> non-const lvalue, and non-const rvalue:
>
>  // C++0x:
>  class vector
>  {
>  public:
>    value_type & at(size_type) &;
>    value_type && at(size_type) &&;
>    value_type const& at(size_type) const&;
>  };
>
>  // Hypothetical C++ inc. your "qualifiers" keyword:
>  class vector
>  {
>  public:
>    template <qualifiers CV>
>    value_type CV at(size_type) CV;
>  };

Interesting. What would be the most sensible rule for template
parameter deduction in situations like these? For that matter: Should
you be able to explicitly specify such a parameter? Example:

 std::vector<double> vec (1, 3.14159265);
 cout << vec.at<const>(0);

In this case you probably should have declared the member template as

 template <qualifiers CV>
 value_type CV&& at(size_type) CV;

to prevent return-by-value. If this template parameter (for a set of
qualifiers) can be specified explicitly we would also need a syntax to
express an empty qualifier set.

still pondering,
SG


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Niels Dekker - no reply address" <invalid@this.is.invalid>
Date: Sun, 14 Jun 2009 07:25:14 CST
Raw View
"SG" <s.gesemann> wrote:
> It already bugs me that you can't write std::memfun in a
> truly generic way

I assume you mean std::mem_fun. (Mind the underscore!)

> but you have to consider four cases for different
> const/volatile versions of member functions.

That's a pity, indeed.

> IMHO, we ought to be able to handle things like
> noexcept, const, volatile without writing different
> versions for every special case. One approach would
> be to
>
>   o) extend the template system with a new kind of
>      parameter for cv qualifiers

Don't forget the ref-qualifiers!

>   o) make noexcept parameterisable
>
> --------8<--------[ BEGIN hypothetical C++ ]--------8<--------
>
>   template< bool NoExcept, typename Ret, class Clz,
>     qualifiers CV, typename ... Parms >
>   class memfun_t
>   {
>   public:
>     typedef noexcept<NoExcept> Ret (Clz::*pmf_t)(Parms...) CV;
>     typedef Clz CV* objptr_t;
>
>     memfun_t(pmf_t pmf) : pmf(pmf) {}
>
>     noexcept<NoExcept>
>     Ret operator()(objptr_t po, P... params) const
>     {
>       return (*po)(std::forward<P>(params)...);
>     }
>   private:
>     pmf_t pmf;
>   };
>
>   template< bool NoExcept, typename Ret, class Clz,
>     qualifiers CV, typename ... Parms >
>   memfun_t<NoExcept,Ret,Clz,CV,Params...>
>   memfun( noexcept<NoExcept> Ret (Clz::*pmf)(Params...) CV )
>   {
>     return memfun_t<NoExcept,Ret,Clz,CV,Params...>(pmf);
>   }
>
> --------8<--------[ END hypothetical C++ ]--------8<--------

I think such a language extension would be very useful. Especially if it
could also help in a different context, having to write overloads for const,
non-const lvalue, and non-const rvalue:

 // C++0x:
 class vector
 {
 public:
   value_type & at(size_type) &;
   value_type && at(size_type) &&;
   value_type const& at(size_type) const&;
 };

 // Hypothetical C++ inc. your "qualifiers" keyword:
 class vector
 {
 public:
   template <qualifiers CV>
   value_type CV at(size_type) CV;
 };


Kind regards, Niels
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]