473,412 Members | 2,075 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,412 software developers and data experts.

How does these code works ?

Hi ,
I am reading some boost code now , and
I got confused by the following code in the
add_reference type trait .

template <class TT&(* is_reference_helper1(wrap<T>) )(wrap<T>);
char is_reference_helper1(...);

template <class Tno_type is_reference_helper2(T&(*)(wrap<T>));
yes_type is_reference_helper2(...);

template <typename T>
struct is_reference_impl
{
BOOST_STATIC_CONSTANT(
bool, value = sizeof(
::boost::detail::is_reference_helper2(

::boost::detail::is_reference_helper1(::boost::typ e_traits::wrap<T>())))
== 1
);
};
Why does function is_reference_helper1 define in such
a way , I can't understand what is it !

Could someone explain these code for me ?
Thank you very much !

Oct 16 '06 #1
7 1490
* Bo Yang:
Hi ,
I am reading some boost code now , and
I got confused by the following code in the
add_reference type trait .

template <class TT&(* is_reference_helper1(wrap<T>) )(wrap<T>);
Yes, that /is/ confusing.

The main problem is perhaps to determine the "innermost" thing declared,
but as the famous Norwegian TV-cook Ingrid Espelid used to say, "but we
have cheated and ... voilą!", and out of the oven she lifted a perfect
.... something ... ; in this case, out of the oven comes the name
is_reference_helper1 (am I mixing metaphors?).

Looking at both sides of that name, the "function call" argument list to
the right takes precedence, it's done first, so to speak (although
nothing is done, but you can read a declaration in much the same way as
it would have been executed as an expression, from inner to outer).

So, hypothetically doing that hypothetical function call, we find that
is_reference_helper1 must be a function taking a wrap<Targument, by value.

Now for the result type, you need to work your way outwards in the
declaration.

And the first thing encountered then is the * on the left.

As an expression that would mean a dereferencing of a pointer, and so in
a declaration it means the thing declared /is/ a pointer (otherwise it
couldn't be dereferenced). So the hypothetical function call yields a
pointer. And so is_reference_helper1 is a function returning a pointer.

But a pointer to what?

Going still farther outwards in the declaration, we have on the left
'T&' and on the right '(wrap<T>)'. Again, if this were an expression
the thing on the right would be a function call's argument list, and
taking precedence. So we now know that the pointer is a pointer to a
function, let's call it ResultFunc, that takes a wrap<Targument by value.

Finally, the result type of ResultFunc is 'T&', a reference to an object
of type T.

So is_reference_helper1 is a function that takes a wrap<Targument by
value, and returns a pointer to a function (the ResultFunc) that takes a
wrap<Targument by value and returns a reference to a T object.

Incidentally, Google code search, applied to 'is_reference_helper1', in
addition to finding that line in the Boost library, turned up this
description from the MSVC port of Andrei Alexandrescu's Loki Library:
"is_reference_helper1 is a function taking a Type2Type<Treturning a
pointer to a function taking a Type2Type<Treturning a T&", which
removes some of the mystery of what that 'wrap<T>' might be.

char is_reference_helper1(...);

template <class Tno_type is_reference_helper2(T&(*)(wrap<T>));
yes_type is_reference_helper2(...);

template <typename T>
struct is_reference_impl
{
BOOST_STATIC_CONSTANT(
bool, value = sizeof(
::boost::detail::is_reference_helper2(

::boost::detail::is_reference_helper1(::boost::typ e_traits::wrap<T>())))
== 1
);
};
Ah, well, I'll leave you to it! <g>

Why does function is_reference_helper1 define in such
a way , I can't understand what is it !
That's because Real Programmers can't be bothered with using 'typedef',
or generally, naming things. After all, if the code could be understood
by others, then one might soon be replaced by someone else. Okay,
that's unfair, especially to Andrei who (it seems) bothered to write the
clear explanatory comment; an equally probable explanation is that in
the heat of the hunt, make that thing work, one has to try out many
different things, and the less typing per thing tried the better, and
then the first thing that works becomes embedded in stone, even if
unreadable, because one is already moving on to the next problem...

Could someone explain these code for me ?
See above.

Thank you very much !
You're welcome.

Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 16 '06 #2

Alf P. Steinbach wrote:
* Bo Yang:
Hi ,
I am reading some boost code now , and
I got confused by the following code in the
add_reference type trait .

template <class TT&(* is_reference_helper1(wrap<T>) )(wrap<T>);

Yes, that /is/ confusing.

The main problem is perhaps to determine the "innermost" thing declared,
but as the famous Norwegian TV-cook Ingrid Espelid used to say, "but we
have cheated and ... voilą!", and out of the oven she lifted a perfect
... something ... ; in this case, out of the oven comes the name
is_reference_helper1 (am I mixing metaphors?).

Looking at both sides of that name, the "function call" argument list to
the right takes precedence, it's done first, so to speak (although
nothing is done, but you can read a declaration in much the same way as
it would have been executed as an expression, from inner to outer).

So, hypothetically doing that hypothetical function call, we find that
is_reference_helper1 must be a function taking a wrap<Targument, by value.

Now for the result type, you need to work your way outwards in the
declaration.

And the first thing encountered then is the * on the left.

As an expression that would mean a dereferencing of a pointer, and so in
a declaration it means the thing declared /is/ a pointer (otherwise it
couldn't be dereferenced). So the hypothetical function call yields a
pointer. And so is_reference_helper1 is a function returning a pointer.

But a pointer to what?

Going still farther outwards in the declaration, we have on the left
'T&' and on the right '(wrap<T>)'. Again, if this were an expression
the thing on the right would be a function call's argument list, and
taking precedence. So we now know that the pointer is a pointer to a
function, let's call it ResultFunc, that takes a wrap<Targument by value.

Finally, the result type of ResultFunc is 'T&', a reference to an object
of type T.

So is_reference_helper1 is a function that takes a wrap<Targument by
value, and returns a pointer to a function (the ResultFunc) that takes a
wrap<Targument by value and returns a reference to a T object.

Incidentally, Google code search, applied to 'is_reference_helper1', in
addition to finding that line in the Boost library, turned up this
description from the MSVC port of Andrei Alexandrescu's Loki Library:
"is_reference_helper1 is a function taking a Type2Type<Treturning a
pointer to a function taking a Type2Type<Treturning a T&", which
removes some of the mystery of what that 'wrap<T>' might be.

Thank you very much .
But , how does these code detect whether
the typename T is a reference or not ?
Although I understand what the code mean , but
I still can't grasp how it tell whether T is a reference ?

Oct 16 '06 #3
* Bo Yang:
But , how does these code detect whether
the typename T is a reference or not ?
Although I understand what the code mean , but
I still can't grasp how it tell whether T is a reference ?
It's a case of SFINAE (Substitution Failure Is Not An Error). Consider
that there are two declarations of is_reference_helper1. Since the
first one has result type T& it fails outright to be matched with T when
T is a reference type, because you can't (currently, as of 2006) form a
reference to a reference (SFINAE kicks in, we have failure, but not an
error). That selects the second declaration of is_reference_helper1,
which has a nice, always valid 'char' result type, but argument type
'...' which is the guaranteed worst match in an overload set, so that it
won't be selected except when SFINAE kicks in for the first one.

Because of the possible failure, and also because T might be any size,
the size of the result type of is_reference_helper1 cannot be used
directly to compute the boolean yes/no of whether T is a reference type.
But the type of the result can be used indirectly, namely to select
from another overload set a function whose result type provides a
distinguishable size. Hence the is_reference_helper2 overloads, with
argument types that match the two possible is_reference_helper1
functions, and easily distinguished result type sizes.

Which result type is plugged into sizeof to make it all happen at
compile time -- and of course, to determine the size, which determines
which is_reference_helper1 was selected, which determines whether T is a
reference type or not.
Hth. (it's a kind of rather ingenious TMP code, relying not only on
undefined functions but also on constructs that won't compile --
except when they're passed by via the SFINAE avoidance mechanism)

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 16 '06 #4

Alf P. Steinbach wrote:
* Bo Yang:
But , how does these code detect whether
the typename T is a reference or not ?
Although I understand what the code mean , but
I still can't grasp how it tell whether T is a reference ?

It's a case of SFINAE (Substitution Failure Is Not An Error). Consider
that there are two declarations of is_reference_helper1. Since the
first one has result type T& it fails outright to be matched with T when
T is a reference type, because you can't (currently, as of 2006) form a
reference to a reference (SFINAE kicks in, we have failure, but not an
error). That selects the second declaration of is_reference_helper1,
which has a nice, always valid 'char' result type, but argument type
'...' which is the guaranteed worst match in an overload set, so that it
won't be selected except when SFINAE kicks in for the first one.

Because of the possible failure, and also because T might be any size,
the size of the result type of is_reference_helper1 cannot be used
directly to compute the boolean yes/no of whether T is a reference type.
But the type of the result can be used indirectly, namely to select
from another overload set a function whose result type provides a
distinguishable size. Hence the is_reference_helper2 overloads, with
argument types that match the two possible is_reference_helper1
functions, and easily distinguished result type sizes.

Which result type is plugged into sizeof to make it all happen at
compile time -- and of course, to determine the size, which determines
which is_reference_helper1 was selected, which determines whether T is a
reference type or not.
Thanks very much , I think I know these code fully .
It is the T& which cause the substitution failed and detect whether T
is a reference type .
So we can just use template

template <typename Tno_type is_reference_helper( T& ) ;
yes_type is_reference_helper(...);

to detect whether the T is a reference .
But the code doesn't , does this just because the code don't
want to construct the object T ?
>
Hth. (it's a kind of rather ingenious TMP code, relying not only on
undefined functions but also on constructs that won't compile --
except when they're passed by via the SFINAE avoidance mechanism)
I find C++ is so profound , I need more time to grasp the concept
of Generic Programming .
- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 16 '06 #5
* Alf P. Steinbach:
* Bo Yang:
>But , how does these code detect whether
the typename T is a reference or not ?
Although I understand what the code mean , but
I still can't grasp how it tell whether T is a reference ?

It's a case of SFINAE (Substitution Failure Is Not An Error). Consider
that there are two declarations of is_reference_helper1. Since the
first one has result type T& it fails outright to be matched with T when
T is a reference type, because you can't (currently, as of 2006) form a
reference to a reference (SFINAE kicks in, we have failure, but not an
error). That selects the second declaration of is_reference_helper1,
which has a nice, always valid 'char' result type, but argument type
'...' which is the guaranteed worst match in an overload set, so that it
won't be selected except when SFINAE kicks in for the first one.

Because of the possible failure, and also because T might be any size,
the size of the result type of is_reference_helper1 cannot be used
directly to compute the boolean yes/no of whether T is a reference type.
But the type of the result can be used indirectly, namely to select
from another overload set a function whose result type provides a
distinguishable size. Hence the is_reference_helper2 overloads, with
argument types that match the two possible is_reference_helper1
functions, and easily distinguished result type sizes.

Which result type is plugged into sizeof to make it all happen at
compile time -- and of course, to determine the size, which determines
which is_reference_helper1 was selected, which determines whether T is a
reference type or not.
Hth. (it's a kind of rather ingenious TMP code, relying not only on
undefined functions but also on constructs that won't compile -- except
when they're passed by via the SFINAE avoidance mechanism)

- Alf
OTOH., I'm not sure I really understand the code (or rather, I'm
beginning to strongly suspect I don't really understand it), because the
following seemingly much simpler code, based on the principles explained
above, seems to do the job:

<code>
#include <iostream>
#include <ostream>
#include <cstddef>

std::size_t const largerThanPointer = 666*sizeof(void*);

template< typename Tstruct TypeCarrier {};

template< typename TT* isRefHelper( TypeCarrier<T);
char (&isRefHelper( ... ))[largerThanPointer];

template< typename T >
class IsRef
{
public:
enum{ yes = (sizeof( isRefHelper( TypeCarrier<T>() ) ) ==
largerThanPointer ) };
};

int main()
{
typedef int NotRef;
typedef int& Ref;

std::cout << "Not ref yields " << IsRef<NotRef>::yes << std::endl;
std::cout << "Ref yields " << IsRef<Ref>::yes << std::endl;
}
</code>
Perhaps it's time to yet again delve into Andrei's book "Modern C++
Design" and check out the rationale... ;-)

Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 16 '06 #6

Alf P. Steinbach wrote:
* Alf P. Steinbach:
* Bo Yang:
But , how does these code detect whether
the typename T is a reference or not ?
Although I understand what the code mean , but
I still can't grasp how it tell whether T is a reference ?
It's a case of SFINAE (Substitution Failure Is Not An Error). Consider
that there are two declarations of is_reference_helper1. Since the
first one has result type T& it fails outright to be matched with T when
T is a reference type, because you can't (currently, as of 2006) form a
reference to a reference (SFINAE kicks in, we have failure, but not an
error). That selects the second declaration of is_reference_helper1,
which has a nice, always valid 'char' result type, but argument type
'...' which is the guaranteed worst match in an overload set, so that it
won't be selected except when SFINAE kicks in for the first one.

Because of the possible failure, and also because T might be any size,
the size of the result type of is_reference_helper1 cannot be used
directly to compute the boolean yes/no of whether T is a reference type.
But the type of the result can be used indirectly, namely to select
from another overload set a function whose result type provides a
distinguishable size. Hence the is_reference_helper2 overloads, with
argument types that match the two possible is_reference_helper1
functions, and easily distinguished result type sizes.

Which result type is plugged into sizeof to make it all happen at
compile time -- and of course, to determine the size, which determines
which is_reference_helper1 was selected, which determines whether T is a
reference type or not.
Hth. (it's a kind of rather ingenious TMP code, relying not only on
undefined functions but also on constructs that won't compile -- except
when they're passed by via the SFINAE avoidance mechanism)

- Alf

OTOH., I'm not sure I really understand the code (or rather, I'm
beginning to strongly suspect I don't really understand it), because the
following seemingly much simpler code, based on the principles explained
above, seems to do the job:

<code>
#include <iostream>
#include <ostream>
#include <cstddef>

std::size_t const largerThanPointer = 666*sizeof(void*);

template< typename Tstruct TypeCarrier {};

template< typename TT* isRefHelper( TypeCarrier<T);
char (&isRefHelper( ... ))[largerThanPointer];
I still can't understand why there must to be the return type
to test the type , why to use a function's argument to test the
type . just like

template <typename Tvoid test( T& ) ;

Oct 16 '06 #7
* Bo Yang:
>
I still can't understand why there must to be the return type
to test the type , why to use a function's argument to test the
type . just like

template <typename Tvoid test( T& ) ;
Sorry, I don't understand the question.

But a general solution to understanding something in programming is:
just try to implement it.

So that's what I advice.
Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 16 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

162
by: Isaac Grover | last post by:
Hi everyone, Just out of curiosity I recently pointed one of my hand-typed pages at the W3 Validator, and my hand-typed code was just ripped to shreds. Then I pointed some major sites...
7
by: Todd Cary | last post by:
I inherited an application where the Flyout works in Firefox but not in IE. My JavaScript background is sparse, so I am not sure how to approach the problem. Any suggestions are welcomed! The...
1
by: Georg Scholz | last post by:
Hello, The class "Control" contains a documented Property "ControlType". So for example, in a form, you can write code like this: Dim c as control set c = me.Controls("textbox1") if...
7
by: Clint Herron | last post by:
Howdy! I posted this question on CSharpCorner.com, but then realized I should probably post it on a more active newsgroup. This will be my only cross-post. I'm creating a game engine, and...
11
by: minnesotti | last post by:
Hi there, I subscribed to a photographic pictures-hosting website which is heavy on JavaScript. My preferred latest browser Mozilla Firefox does not work with it -- no pictures are displayed and...
14
by: Anoop | last post by:
Hi, I am new to this newsgroup and need help in the following questions. 1. I am workin' on a GUI application. Does C# provides Layout Managers the way Java does to design GUI? I know that it...
0
by: pkolinko | last post by:
Hi everyone, I am writing a small low level embedded USB application using C++/CLI windows Forms. I am sort of new to the C++/CLI and having trouble understanding what happens in this very...
113
by: John Nagle | last post by:
The major complaint I have about Python is that the packages which connect it to other software components all seem to have serious problems. As long as you don't need to talk to anything outside...
10
by: paulie | last post by:
Hi, I have been experiencing an issue when trying to use AJAX to reload a DIV area using a timer of 2000ms, which contains a html page with another DIV and javascript. Scenario -------------...
1
by: jabbari | last post by:
Hello, Please Help us...! I have a big problem ,so i searched on google and other search engine ,then I realized that so many other people have the same problem and they, all, have'nt been able to...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.