472,984 Members | 2,025 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

[Generic/Polytypic] Template not quite right

/*
I've been experimenting with some generic/polytypic programs, and
I've stumbled on to a problem that I can't quite figure out. In the
program below, I'm trying to define a generic version of "transform"
which works not only on lists, but lists of list, lists of lists of
lists, etc. I'm calling it "fmap" and it passes around actual lists
instead of iterators (for now). In order to get it to work, I thought
I'd have one templated function which works on just lists (call this is
base case) and another templated function which works on lists of lists
of lists... and recursively calls "fmap" until we get down to a simple
list of something and then we call the base case. My current thinking
is that the "fmap" labeled Recursive Case #1 should be the most
general,
and should make all the code below work properly. Unfortunately, my
intuition appears to be wrong, and I needed to define Recursive Cases
#2
and #3 in order to get the examples below to work. Can anyone help me
see why #1 doesn't work? Commenting out the "#define REC_No_2_3"
results in errors like...

t.C:122: error: No match for 'fmap(list<list<int> > &, char(&)(int))'
t.C:126: error: No match for 'fmap(list<list<int> > &, int(&)(int))'
t.C:130: error: No match for 'fmap(list<list<list<int> > > &,
int(&)(int))'

....for the first error, it seems like it should be able to match my #1
by instantiating...
In = list
Out = list
T = int
U = char

....Or maybe you can provide a link to other people working on polytypic
programming in C++? (You can look at a syntax highlighted version of
the code at... http://sleepingsquirrel.org/cpp/test_fmap.cpp.html )

Thanks,

Greg Buchholz
*/
#include<iostream>
#include<list>
#include<algorithm>
#include<functional>
#include<iterator>

#define REC_No_2_3 //undef to comment out extra code that I think
//shouldn't be needed.
using namespace std;

//Base Case: No further calls to "fmap"
template<template<class> class In, class T, class U>
In<U> fmap(In<T> i, U (*f)(T))
{
In<U> temp;
transform(i.begin(),i.end(),back_inserter(temp),f) ;
return temp;
}

//Recursive Case #1: Should be used with nested lists
template<template<class>class In, template<class> class Out, class T,
class U>
list<Out<U> > fmap(list<In<T> > l, U (*f)(T))
{
list<Out<U> > temp;
// Using "transform" doesn't work, complaining of unresolved
overloading
// of bind2nd...
// transform(l.begin(),l.end(),back_inserter(temp),
bind2nd(fmap,f));
// return temp;

for(typename list<In<T> >::const_iterator iter = l.begin();
iter != l.end(); ++iter)
{
temp.push_back(fmap(*iter,f));
}
return temp;
}

#ifdef REC_No_2_3
//Recursive Case #2: Note that the output data structure has to be the
// same as the input data structure.
template<class In, class Func> list<list<In> > fmap(list<list<In> > l,
Func f)
{
list<list<In> > temp;
for(typename list<list<In> >::const_iterator iter = l.begin();
iter != l.end(); ++iter)
{
temp.push_back(fmap(*iter,f));
}
return temp;
}

//Recursive Case #3: Seems like the problem here is that "Out" doesn't
// depend on "In", so "Out" has to be manually
specified.
template<class In, class Out, class Func>
list<list<Out> > fmap(list<list<In> > l, Func f)
{
list<list<Out> > temp;
for(typename list<list<In> >::const_iterator iter = l.begin();
iter != l.end(); ++iter)
{
temp.push_back(fmap(*iter,f));
}
return temp;
}
#endif

int lsize(list<int> l) //compute number of elements in a list
{
int size = 0;
for(list<int>::const_iterator i = l.begin(); i!= l.end(); ++i)
size++;
return size;
}

int inc(int x){ return x+1; }
char to_char(int x){ return 'A'+(char)x; }

template<class T> std::ostream& operator<<(std::ostream&, const
std::list<T>&);

int main(int argc, char* argv[])
{
int tmp[] = {1,2,3};
list<int> simple_list(tmp,tmp+3);

list<list<int> > lol;
lol.push_back(simple_list);
lol.push_back(simple_list);

cout << "to_char of simple list: " << simple_list << " => "
<< fmap(simple_list,to_char) << endl;

#ifndef REC_No_2_3
cout << "lol = " << lol << endl
<< "lengths of lol's lists = " << fmap(lol,lsize) << endl;
#endif

//This example uses Recursive #3.
cout << "to_char of lol: "<< lol << " => "
<< fmap<int,char>(lol,to_char) << endl;

//The next two "fmap"s use Recursive #2.
cout << " inc of lol: "<< lol << " => "
<< fmap(lol,inc) << endl;

list<list<list<int> > > lolol;
lolol.push_back(lol);
cout << " inc of lolol: "<< lolol << " => " << fmap(lolol,inc) <<
endl;

//And I haven't yet got this to work...
//cout << "to_char of lolol: "<< lolol << " => "
// << fmap(lolol,to_char) << endl;

return 0;
}

template<class T> std::ostream& operator<<(std::ostream& o, const
std::list<T>& l)
{
o << "[";
for(typename std::list<T>::const_iterator i = l.begin(); i !=
--l.end(); ++i)
o << *i << ",";
return o << *(--l.end()) << "]";
}

Mar 17 '06 #1
2 1934
/*
OK, I've solved part of my problem. In "Recursive Case #1",
changing the template parameter "Out" to "In" allows a few more of my
examples to run. Now I need to know how to pass a multiply nested
template to a templated template parameter (er, there's probably a
better, more techinical wording for that). For example (from below)...

fmap<list<list>,list<list> >(lolol,inc)

....isn't proper syntax. My compiler (g++) complains...

t.C:113: error: type/value mismatch at argument 1 in template parameter
list for 'template<class _Tp, class _Alloc> class list'
t.C:113: error: expected a type, got 'list'
t.C:113: error: template argument 2 is invalid
t.C:113: error: type/value mismatch at argument 1 in template parameter
list for 'template<class _Tp, class _Alloc> class list'
t.C:113: error: expected a type, got 'list'
t.C:113: error: template argument 2 is invalid
t.C:113: error: No match for 'fmap(list<list<list<int> > > &, int
(&)(int))'

....And I'd appreciate any tips or hints on changes I could make to the
code in order to help the compiler deduce the template parameters
without having to manually specify them.

Thanks,

Greg Buchholz
*/
#include<iostream>
#include<list>
#include<algorithm>
#include<functional>
#include<iterator>

#define PROBLEM_AREA //undef to comment out problem areas and
//successfully compile the rest of program.
using namespace std;

//Base Case: No further calls to "fmap"
template<template<class> class In, class T, class U>
In<U> fmap(In<T> i, U (*f)(T))
{
In<U> temp;
transform(i.begin(),i.end(),back_inserter(temp),f) ;
return temp;
}

//Recursive Case #1: Should be used with nested lists
template<template<class> class In, template<class> class Out, class T,
class U>
list<In<U> > fmap(list<In<T> > l, U (*f)(T))
{
list<In<U> > temp;

for(typename list<In<T> >::const_iterator iter = l.begin();
iter != l.end(); ++iter)
{
temp.push_back(fmap(*iter,f));
}
return temp;
}

int lsize(list<int> l) //compute number of elements in a list
{
int size = 0;
for(list<int>::const_iterator i = l.begin(); i!= l.end(); ++i)
size++;
return size;
}

int inc(int x){ return x+1; }
char to_char(int x){ return 'A'+(char)x; }

template<class T> std::ostream& operator<<(std::ostream&, const
std::list<T>&);

int main(int argc, char* argv[])
{
int tmp[] = {1,2,3};
list<int> simple_list(tmp,tmp+3);

list<list<int> > lol;
lol.push_back(simple_list);
lol.push_back(simple_list);

cout << "to_char of simple list: " << simple_list << " => "
<< fmap(simple_list,to_char) << endl;

cout << "lol = " << lol << endl
<< "lengths of lol's lists = " << fmap(lol,lsize) << endl;

cout << "to_char of lol: "<< lol << " => "
<< fmap<list,list,int,char>(lol,to_char) << endl;

cout << " inc of lol: "<< lol << " => "
<< fmap<list,list>(lol,inc) << endl;

list<list<list<int> > > lolol;
lolol.push_back(lol);

/* How do you tell the compiler that the template parameters
are lists of lists? */
#ifdef PROBLEM_AREA
cout << " inc of lolol: "<< lolol << " => "
<< fmap<list<list>,list<list> >(lolol,inc) << endl;

cout << "to_char of lolol: "<< lolol << " => "
<< fmap<list<list>,list<list> >(lolol,to_char) << endl;
#endif

return 0;
}

template<class T> std::ostream& operator<<(std::ostream& o, const
std::list<T>& l)
{
o << "[";
for(typename std::list<T>::const_iterator i = l.begin(); i !=
--l.end(); ++i)
o << *i << ",";
return o << *(--l.end()) << "]";
}

Mar 17 '06 #2
change to:
#include<iostream>
#include<list>
#include<algorithm>
#include<functional>
#include<iterator>
using namespace std;

//Base Case: No further calls to "fmap"
template<template<class> class Alloc, template<class, class> class
Container, class T, class U>
Container<U, Alloc<U> > fmap(Container<T, Alloc<T> > i, U (*f)(T))
{
Container<U, Alloc<U> > temp;
transform(i.begin(),i.end(),back_inserter(temp),f) ;
return temp;
}

//Recursive Case #1: Should be used with nested lists
template<template<class> class Alloc, template<class, class> class
Container, class T, class U>
list<Container<U, Alloc<U> > > fmap(list<Container<T, Alloc<T> > > l, U
(*f)(T))
{
list<Container<U, Alloc<U> > > temp;

for(typename list<Container<T, Alloc<T> > >::const_iterator iter =
l.begin();
iter != l.end(); ++iter)
{
temp.push_back(fmap(*iter,f));
}
return temp;
}

int lsize(list<int> l) //compute number of elements in a list
{
int size = 0;
for(list<int>::const_iterator i = l.begin(); i!= l.end(); ++i)
size++;
return size;
}

int inc(int x){ return x+1; }
char to_char(int x){ return 'A'+(char)x; }

template<class T> std::ostream& operator<<(std::ostream& o, const
std::list<T>& l)
{
o << "[";
for(typename std::list<T>::const_iterator i = l.begin(); i !=
--l.end(); ++i)
o << *i << ",";
return o << *(--l.end()) << "]";
}

int main(int argc, char* argv[])
{
int tmp[] = {1,2,3};
list<int> simple_list(tmp,tmp+3);

list<list<int> > lol;
lol.push_back(simple_list);
lol.push_back(simple_list);

cout << "to_char of simple list: " << simple_list << " => "
<< fmap(simple_list,to_char) << endl;

cout << "lol = " << lol << endl
<< "lengths of lol's lists = " << fmap(lol,lsize) << endl;

cout << "to_char of lol: "<< lol << " => "
<< fmap(lol,to_char) << endl;

cout << " inc of lol: "<< lol << " => "
<< fmap(lol,inc) << endl;

list<list<list<int> > > lolol;
lolol.push_back(lol);

return 0;
}
you know std::list's declare is
template<class _Ty,
class _Ax = allocator<_Ty> >
class list;
so i add the Alloc to tell complier to deduce the params.
and i change to In to Container.
and
fmap<list<list>,list<list> >(lolol,inc)
....isn't proper syntax. My compiler (g++) complains...
because the function tell the complier wrong infors, so she can not
deduce the right params

so should add somethings likes:
template<typename L>
list<L> incL(list<L>);

cheers!

Mar 18 '06 #3

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

Similar topics

16
by: Roman Suzi | last post by:
Hi, I wonder, does Python support generic programming paradigm, and to what extent (I guess, it doesn't do it in full)? And (or) does it move in that direction? Will we ever see concept...
0
by: Christopher Benson-Manica | last post by:
(To the extent that this is a rehash of earlier questions, sorry.) I feel like I'm starting to get the hang of how to make classes work with << and >>, so now I have the (possibly dumb) idea to...
7
by: Master of C++ | last post by:
Hello Folks, I have a programming dilemma with templates and "genericity". I can think of a few solutions, but I am not sure which one is the best in terms of genetic C++ style. Any suggestions...
17
by: Andreas Huber | last post by:
What follows is a discussion of my experience with .NET generics & the ..NET framework (as implemented in the Visual Studio 2005 Beta 1), which leads to questions as to why certain things are the...
28
by: steve yee | last post by:
i think c should adapt c++ template standard, as well as namespace. if so, c can replace c++ in many cases.
1
by: interX | last post by:
Hi I'm new in VC++ and have a question to generics. I have a generic class, which contains an array of the generic type. This array I can pin and then I would like to get an unmanaged pointer to...
1
by: raylopez99 | last post by:
I seem to get name collision between the Generic collection SortedList and C++.NET Framework collection SortedList. How to resolve? Here are the libraries that seem to clash:...
3
by: gary.bernstein | last post by:
I want to call a singleton getInstance function to retrieve a templatized object without knowing what types were used to create the singleton object in the first call to getInstance. How can I do...
3
by: Boris | last post by:
I have a class which should like this ideally: generic <typename T> public ref class ManagedClass { T ^managedMember; UnmanagedClass<U*unmanagedMember; }; I actually would like to specify...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
4
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

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.