473,847 Members | 2,427 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

tr1::reference_ wrapper, sfinae and result_type definition

Hello,

I'm trying to find a (sfinae powered) way to verify if a particular
type declares a subtype (either using typedef or by declaring a
subclass). To be more concrete, let's say that I'm trying to see how to
implement a tiny part of tr1::reference_ wrapper, more exactly the
definition of its weak result type.

Let's imagine that class A and B inherit both std::unary_func tion and
std::binary_fun ction. As such, they also inherit
unary_function: :result_type and binary_function ::result_type.
reference_wrapp er<Aand reference_wrapp er<Bshall now define their
weak result type.

Let's use these definitions:

------------8<----------------------------------------

struct A :
unary_function< int, int>,
binary_function <float, float, float>
{
typedef bool result_type;
};

struct B :
unary_function< int, int>,
binary_function <float, float, float>
{ };

------------>8----------------------------------------

A has in fact 3 different result_type (A::unary_funct ion::result_typ e,
A::binary_funct ion::result_typ e and A::result_type) . The TR1 tells me
that I should define reference_wrapp er<A>::result_t ype as
A::result_type (quite logical).

The problem comes if I have to consider B, as I find the wording of the
TR1 quite obscure in this case. As I understand it, I have two
possibilities:

1) either I don't define reference_wrapp er<B>::result_t ype, because B
doesn't define result_type (although it inherit a result_type member
from both unary_function and binary_function )

2) or I define reference_wrapp er<B>::result_t ype as either
B::unary_functi on::result_type or B::binary_funct ion::result_typ e
(which doesn't make much sense, since these types are different. So
maybe I should only define reference_wrapp er<B>::result_t ype if
B::unary_functi on::result_type and B::binary_funct ion::result_typ e are
the same).

But that's not only the sole problem in this area. Another one comes if
I want to verify if a class defines a result_type subtype. Consequently
to the C++ name lookup scheme, if result_type is not defined in a class
C but is defined (and accessible) in a super class, then C::result_type
is known and can hardly be differentiated from a subtype of C.

It means that I cannot differentiate between the cases of class A and
class B above - I have no way to find that result_type is not defined
in class B but only in its superclass. The problem is that since B has
two superclass that define their own result_type, B::result_type
results in a compile time ambiguousity - the compiler shoke (and he's
quite right).

Until now, I used this code (inherited from boost, I think) to try to
see if a type was defined in a class:

------------8<----------------------------------------

template <class tclass has_result_type
{
template <class ustruct wrapper { }
typedef char one[1];
typedef char two[2];
template <class ustatic one& test(wrapper<u: :result_type>*) ;
template <class ustatic two& test(...);
public:
static const bool value = sizeof(test<t>( 0)) == sizeof(one);
};

------------>8----------------------------------------

Gnu's g++ compiler is quite happy with this code -
has_result_type <A>::value is true, and has_result_type <B>::value is
false. MS VC++.NET 2005 compiler is a lot more problematic: both
has_result_type <A>::value and has_result_type <B>::value are true -
which is nearly logical, since B really has (at least) a definition of
result_type. Finally, the Comeau C++ compiler shoke - because
u::result_type is ambiguous when u = B (this is probably the most
logical behavior, as I understand how the standard defines name
lookup).

As a consequence, either this code is nonportable or it is just non
standard compliant.

Which means, in turn, that I still have no way to differentiate between
class A and class B using a generic way.

So far, I have two questions:
1) what is the correct, official intrepretation of the weak result type
definition in the TR1? (I personnally feel that the wording of this
definition should be changed to be clearer)
2) regardless of this interpretation, how can I differientiate between
the two cases I presented (class A and class B)?

This issue has bugged be for two weeks now, and I'm not able to devise
a solution to this problem.

Thanks for your time, and happy answering! :)

-- Emmanuel Deloget, Artware

Nov 29 '06 #1
2 2243
Emmanuel Deloget wrote:
>
Let's use these definitions:

------------8<----------------------------------------

struct A :
unary_function< int, int>,
binary_function <float, float, float>
{
typedef bool result_type;
};

struct B :
unary_function< int, int>,
binary_function <float, float, float>
{ };

------------>8----------------------------------------

A has in fact 3 different result_type (A::unary_funct ion::result_typ e,
A::binary_funct ion::result_typ e and A::result_type) . The TR1 tells me
that I should define reference_wrapp er<A>::result_t ype as
A::result_type (quite logical).
Not really. A and B should each be derived from either unary_function or
from binary_function , but not both. Keep in mind that the requirements
for defining result_type are for backward compatibility with today's
callable types and with today's compilers. Callable types in the current
standard have one function call operator, so when you write that type
you know exactly how many arguments that function call operator takes,
so you can choose unary_function or binary_function as appropriate. (See
chapter 6 of my book, "The Standard C++ Library Extensions", for more
details).

struct A : unary_function< int, int>
{
int operator()(int) ;
};

or

struct A : binary_function <float, float, float>
{
float operator()(floa t, float);
};

If you're trying to do something more sophisticated with multiple
function call operators and different numbers of arguments you've got
problems: the support isn't quite there today. Eventually you'll be able
to do something like this:

struct A
{
int operator()(int) ;
float operator()(floa t);
};

A a;
reference_wrapp er<Aawrap = a;
a(3);
a(4.5);

But at present, reference_wrapp er isn't able to figure out the return
type of that function call operation. It relies on result_of, which, for
now, relies on finding result_type in the type that you're using. And,
as you've mentioned, it's hard to have more than one result_type in a class.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Nov 29 '06 #2
Pete Becker a écrit :
Not really. A and B should each be derived from either unary_function or
from binary_function , but not both. Keep in mind that the requirements
for defining result_type are for backward compatibility with today's
callable types and with today's compilers. Callable types in the current
standard have one function call operator, so when you write that type
you know exactly how many arguments that function call operator takes,
so you can choose unary_function or binary_function as appropriate. (See
chapter 6 of my book, "The Standard C++ Library Extensions", for more
details).

[snip-a-lot]

If you're trying to do something more sophisticated with multiple
function call operators and different numbers of arguments you've got
problems: the support isn't quite there today. Eventually you'll be able
to do something like this:

struct A
{
int operator()(int) ;
float operator()(floa t);
};

A a;
reference_wrapp er<Aawrap = a;
a(3);
a(4.5);

But at present, reference_wrapp er isn't able to figure out the return
type of that function call operation. It relies on result_of, which, for
now, relies on finding result_type in the type that you're using. And,
as you've mentioned, it's hard to have more than one result_type in a class.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
First, thanks for you answer.

Second, it appears that if the class could inherit either
unary_function or binary_function (but not both) to be
reference_wrapp ed, then the TR1 (or at least the TR1 draft that can be
downloaded from the WG21 website) is not adequately worded (no offense
intended), as its words implies that both should be supported: 2.1.2
§3 and 2.1.2 §4 are not mutually exclusive, resulting in your
servitor trying to implement the union of both clauses. It would also
simplify things a lot (at least, I'd be able to code this ^_^) ( the
new C++0x working draft also use a similar wording BTW, in which mutual
exclusivity is not implied).

I guess I can now move on some another annoying problem :)

Regards,

-- Emmanuel Deloget, Artware

Nov 29 '06 #3

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

Similar topics

1
1753
by: Andrew Brampton | last post by:
Hi, I'm using Boost::thread and when constructing the thread object I need to pass a Function Object so that the new thread is spawned by calling this object's operator(). So I have classes like this class NewThread { NewThread() { // Some kind of construction } void operator()() {
6
4161
by: Caleb | last post by:
I have a class that has two member functions of the same name: class MyClass { public: void someFunction(int arg); void someFunction(int arg, char blah); }; I'm trying to get a tr1::functional to the first one, for example:
21
2229
by: George Exarchakos | last post by:
Hi everyone, I'd like your help... Can we have a std::list<BASEwhere BASE be the base class of a class hierarchy? I want to add to this list objects that are inherited from BASE class but not necessarily the same... class base { int x;
3
3228
by: Emmanuel Deloget | last post by:
Hello y'all, I'm currently writing a serie of blog tickets about the TR1, both from a definition point of view and from an implementation point of view. The next iteration in the series deals with the smart pointer sub- library in the TR1 (weak_ptr, shared_ptr, enable_shared_from_this), and guess what, I have a few question about the implementation of all this. Before I ask my question, I'd like to say that I studied all the
6
2032
by: Jess | last post by:
Hello, Is it possible to put object references into a container, such as a vector? I tried the following, but the compiler gave me lots of error messages. struct A{ int x; };
3
2406
by: asclearuc | last post by:
Hello Is it possible to use map<string&, string&>? Why I need it. I have a large amount of data obtained from XML file. I should do processing of this data. The processing takes many stages, and could be done using std::map templates. But new instance of std::map is required on each stage.
7
4129
by: Jeff Schwab | last post by:
The latest GCC (4.2.3) gives a warning if a tr1::array is initialized with the traditional syntax: #include <iostream> #include <tr1/array> int main() { std::tr1::array<int, 35a = { 0 }; std::cout << a << '\n'; }
5
3186
by: zr | last post by:
Hi, Is there a way to initialize a std::tr1::array with a pre-allocated built-in array in a copy-less assignment, such that both will point to the same memory? Vice-versa is easy to do, simply use std::t1::array::data() and assign the returned value to the c-style pointer; if STL does not support this, is there any other library that has such a container (maybe BOOST)?
1
2504
by: Felipe Farinon | last post by:
1) I was wordering why the reference_wrapper’s constructor is explicit. For me it seens to be more useful wihout it. I want to create a “view” of STL containers and the reference_wrapper class is not so useful in this context. For example, int data = { 3, 7, 4 }; std::vector<std::tr1::reference_wrapper<int v; for (int i = 0; i < 3; ++i)
0
9727
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10981
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10706
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9477
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7879
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7050
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 then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5907
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
4113
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3158
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.