Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Specializing Perfect Forwarding Templates?

Reply
Thread Tools

Specializing Perfect Forwarding Templates?

 
 
crea
Guest
Posts: n/a
 
      03-16-2011
>Scott Meyers wrote:

Are you the Scott Meyers who wrotes foreword to book "Modern C++ Design" ?


 
Reply With Quote
 
 
 
 
SG
Guest
Posts: n/a
 
      03-16-2011
On 16 Mrz., 12:12, itaj sherman wrote:
> On Mar 16, 1:10*pm, itaj sherman wrote:
>
> oops specialization syntax:
>
> > template< typename T* >
> > class fwd_internal

>
> template< typename T >
> class fwd_internal< T* >


In addition, you have to replace

fwd_internal<T>::call(etc);

with

typedef typename std::decay<T>::type Td;
fwd_internal<Td>::call(etc);

to get rid of cv qualifiers and the case when T is deduced to to be an
lvalue reference due to the "funny/special" deduction rule that allows
perfect forwarding.

Cheers!
SG
 
Reply With Quote
 
 
 
 
Balog Pal
Guest
Posts: n/a
 
      03-16-2011
"crea" <>
> >Scott Meyers wrote:

>
> Are you the Scott Meyers who wrotes foreword to book "Modern C++ Design" ?


He is. Though i though he's more famous for full books of his own writing
and other mentoring activity.

like recent
http://cppandbeyond.com/2011/03/14/r...1-is-now-open/

 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      03-16-2011
On 3/15/2011 10:22 PM, Scott Meyers wrote:

> template<typename T>
> void fwd(T*&& param)
> {
> std::cout << "T*&& forwarding template => ";
> f(std::forward<T*>(param));
> }
>


Couple issues here. T can never cause reference "decay". If T is an
lvalue reference then you have the strange parameter type "T&*&&". If T
is an rvalue reference then you have the strange parameter type
"T&&*&&". To implement a perfect forwarding function you need to be
relying on the fact that & && is & and && && is && so that when T is an
lvalue reference, the parameter to the function is, and visa-versa.

Second issue is that std::forward works similarly. It's simply a
template function that takes a T&& and returns T.

Since the parameter for your function is always going to be an rvalue
reference you can expect that lvalue references can't be passed into it
without calling std::move.

You can do what you're trying to do with a dispatching pattern:

#include <iostream>
#include <type_traits>

template < bool Match >
struct function_impl
{
template < typename T >
static void apply(T&& t)
{
std::cout << "Generic version called.\n";
}
};

template < >
struct function_impl<true>
{
template < typename T >
static void apply(T&& t)
{
std::cout << "Specific version called.\n";
}
};

template < typename T >
void f(T&& t)
{
function_impl< std::is_pointer< typename
std::remove_reference<T>::type >::value >::apply(std::forward<T>(t));
}

int * get_ptr() { return nullptr; }
int get_value() { return 0; }

int main()
{
int val = get_value();
int * ptr = get_ptr();

f(val);
f(ptr);
f(get_value());
f(get_ptr());
}

Specific needs may of course mean a more complicated construct.

--
http://crazycpp.wordpress.com
 
Reply With Quote
 
Scott Meyers
Guest
Posts: n/a
 
      03-16-2011
On 3/16/2011 9:47 AM, Noah Roberts wrote:
> You can do what you're trying to do with a dispatching pattern:


Simple testing suggests I can achieve the same end with less work and
using an arguably clearer approach via enable_if. Overloading my
forwarding template as follows works for me with VC10 and gcc 4.5 (on
simple tests):

template<typename T>
typename std::enable_if<
!std::is_pointer<
typename std::remove_reference<T>::type
>::value
>::type

fwd(T&& param)
{
std::cout << "General forwarding template => ";
f(std::forward<T>(param));
}

template<typename T>
typename std::enable_if<
std::is_pointer<
typename std::remove_reference<T>::type
>::value
>::type

fwd(T&& param)
{
std::cout << "Pointer forwarding template => ";
f(std::forward<T>(param));
}

Am I overlooking a drawback to this technique?

While playing around with this, I was surprised to find that there is no
disable_if in C++0x. Yes, there's no need for it (as shown above), but
it has an established usage history (e.g., in Boost). Does anybody
happen to know why it's not in C++0x?

Thanks,

Scott

--
* C++ and Beyond: Meyers, Sutter, & Alexandrescu, Aug. 7-10 in Banff
(http://cppandbeyond.com/)

 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      03-16-2011
On 3/16/2011 10:20 AM, Scott Meyers wrote:
> On 3/16/2011 9:47 AM, Noah Roberts wrote:
>> You can do what you're trying to do with a dispatching pattern:

>
> Simple testing suggests I can achieve the same end with less work and
> using an arguably clearer approach via enable_if.


Entirely possible as you show. Arguably cleaner but I tend to disagree.
I've found that although enable_if works reasonably well when you're
trying to match specific concepts and/or types, when you begin having to
exclude these concepts in the other overloads/specializations to resolve
ambiguity the scaling factor explodes and it tends, in my opinion, to be
less legible than dispatching versions.

If, for example, you needed to overload both versions for some specific
concept, a combination of dispatching at the is_pointer level and either
enable_if or a different dispatch for the function call would probably
end up in slightly more legible code. It would also tend to create more
reuse because the is_pointer bit is already resolved by the general layer.

> Am I overlooking a drawback to this technique?


Scalability would be my primary technical concern. Preference would
guide me to prefer the dispatch version otherwise, though I'm sure I
could be convinced otherwise by a good reason to prefer the enable_if
version.

>
> While playing around with this, I was surprised to find that there is no
> disable_if in C++0x. Yes, there's no need for it (as shown above), but
> it has an established usage history (e.g., in Boost). Does anybody
> happen to know why it's not in C++0x?


I wouldn't really know. Perhaps it was just one less thing to argue
about

--
http://crazycpp.wordpress.com
 
Reply With Quote
 
Marc
Guest
Posts: n/a
 
      03-16-2011
Scott Meyers wrote:

> Simple testing suggests I can achieve the same end with less work and
> using an arguably clearer approach via enable_if. Overloading my
> forwarding template as follows works for me with VC10 and gcc 4.5 (on
> simple tests):
>
> template<typename T>
> typename std::enable_if<
> !std::is_pointer<
> typename std::remove_reference<T>::type
> >::value
> >::type

> fwd(T&& param)
> {
> std::cout << "General forwarding template => ";
> f(std::forward<T>(param));
> }
>
> template<typename T>
> typename std::enable_if<
> std::is_pointer<
> typename std::remove_reference<T>::type
> >::value
> >::type

> fwd(T&& param)
> {
> std::cout << "Pointer forwarding template => ";
> f(std::forward<T>(param));
> }
>
> Am I overlooking a drawback to this technique?


That's the natural solution, but it doesn't scale so nicely if you
want to have several specializations. Besides, you need to know all
specializations in advance. Hence the solutions using a traits class
or a dispatcher class or...

> While playing around with this, I was surprised to find that there is no
> disable_if in C++0x. Yes, there's no need for it (as shown above), but
> it has an established usage history (e.g., in Boost).


I didn't even know it was in boost. It just seems so natural to negate
the argument...
 
Reply With Quote
 
Scott Meyers
Guest
Posts: n/a
 
      03-16-2011
On 3/16/2011 10:44 AM, Marc wrote:
> I didn't even know it was in boost. It just seems so natural to negate
> the argument...


As far as I know, it's been around pretty much since the beginning. The
first time I read about enable_if was in the 2003 C/C++ Users Journal
article (available at http://drdobbs.com/cpp/184401659 ), and disable_if
was introduced in the same sentence as enable_if.

Scott

--
* C++ and Beyond: Meyers, Sutter, & Alexandrescu, Aug 7-10 in Banff
(http://cppandbeyond.com/)
 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      03-16-2011
On 16 Mrz., 18:44, Marc wrote:
> Scott Meyers *wrote:
> > [...]

> [...] but it doesn't scale so nicely if you
> want to have several specializations. Besides, you need to know all
> specializations in advance.


Exactly. This is because there is no partial ordering for multiple
matches since these "constraints" are not considered during overload
resolution.

Concepts indented to fix that by concept-based overloading where the
partial ordering is established via concept inheritance. One work
around for the lack of concept-based overloading is tag dispatching.
But this also requires one additional layer of indirection and is not
any better than the approaches that have been shown here already.

SG
 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      03-16-2011
On 3/16/2011 10:20 AM, Scott Meyers wrote:

> While playing around with this, I was surprised to find that there is no
> disable_if in C++0x. Yes, there's no need for it (as shown above), but
> it has an established usage history (e.g., in Boost). Does anybody
> happen to know why it's not in C++0x?


Actually, there's a significant difference between std::enable_if and
boost::enable_if that may be the main reason why disable_if is in boost
and not std.

std::enable_if< !is_pointer<T>::value ... >

That's ok.

boost::enable_if< !is_pointer<T>::value ... >

Not ok. You either need to use enable_if_c or something like so:

boost::enable_if< boost::mpl::not_< is_pointer<T> > ... >

Since "metafunction" didn't make it into the standard that I know of it
would be hard to specify an enable_if that used one. Since its easy to
negate a value, compared to a bool metafunction, it could be that the
committee simply didn't see it as vital while it's certainly a benefit
in boost. Once the decision was made to implement in terms of value
rather than metafunction it probably just fell out.

--
http://crazycpp.wordpress.com
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
strange compile problem regarding const-ref v.s. perfect forwarding huili80@gmail.com C++ 3 10-29-2012 09:11 PM
Perfect Forwarding in Runtime (rvalue reference) dervih C++ 3 07-13-2012 02:03 PM
using std::function, std::bind, perfect forwarding Andrew Tomazos C++ 1 12-23-2011 10:19 AM
Perfect Forwarding + static_assert [C++0x] Scott Meyers C++ 6 12-05-2010 08:21 PM
Perfect function forwarding Alexis Nikichine Javascript 6 12-28-2005 02:39 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57