472,347 Members | 2,400 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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

Comparator template argument in recursive templates?

While thunbing through _C++ Templates, The Complete Guide_ (reckon I aught
to read it?) I came across a discussion of using templates to "unroll"
loops. I thought that looked like a good idea, so I decided to try it on
some code I'm writing. The idea is to use template objects to perform what
happens in traditional nested for() loops.

for(int row = 0; row < num_rows; row++)
{
for(int col = 0; col < num_cols; col++)
{
operation(a1[row][col], a2[row][col]);
}
}

This code (I believe) accomplishes my objective for '==':
/* gnuBoilerplate.hh */

#ifndef _GNU_BOILERPLATE_HH_
#define _GNU_BOILERPLATE_HH_
/************************************************** *************************
* Copyright (C) 2004 by Steven T. Hatton *
* ha*****@globalsymmetry.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
************************************************** *************************/
#endif
/* Array2Equal.hh */
#ifndef STH_VMATH_ARRAY2EQUAL_HH_
#define STH_VMATH_ARRAY2EQUAL_HH_
#include "gnuBoilerplate.hh"
#include "ArrayEqual.hh"

namespace sth{
namespace vmath{

template <unsigned NUMBER_OF_ROWS,unsigned NUMBER_OF_COLUMNS, typename
T >
class Array2Equal{
public:
static bool equal(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return ArrayEqual<NUMBER_OF_COLUMNS, T>::equal(a1[NUMBER_OF_ROWS-1], a
[NUMBER_OF_ROWS-1])
&& Array2Equal<NUMBER_OF_ROWS - 1, NUMBER_OF_COLUMNS, T>::equal(a1, a2);
}
};

template <unsigned NUMBER_OF_COLUMNS, typename T >
class Array2Equal<1, NUMBER_OF_COLUMNS, T>{
public:
static bool equal(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return ArrayEqual<NUMBER_OF_COLUMNS, T>::equal(a1[0], a2[0]);
}
};

template<unsigned NUMBER_OF_ROWS, unsigned NUMBER_OF_COLUMNS, typename
T >
inline bool equal2Array(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return Array2Equal<NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, T >::equal(a1,
a2);
}

}
}

#endif

/* ArrayEqual.hh */
#ifndef ARRAYEQUAL_HH
#define ARRAYEQUAL_HH
#include "gnuBoilerplate.hh"

namespace sth{
namespace vmath{

template <unsigned NUMBER_OF_ELEMENTS, typename T>
class ArrayEqual{
public:
static bool equal(const T* a1, const T* a2)
{
return (*a2 == *a1)
&& ArrayEqual<NUMBER_OF_ELEMENTS - 1, T>::equal(a1 + 1, a2 + 1);
}
};

template <typename T >
class ArrayEqual<1,T>{
public:
static bool equal(const T* a1, const T* a2)
{
return *a2 == *a1;
}
};

template <unsigned NUMBER_OF_ELEMENTS, typename T >
inline bool equalArray(const T* a1, const T* a2)
{
return ArrayEqual<NUMBER_OF_ELEMENTS, T>::equal(a1, a2);
}

}
}

#endif

I tried very hard to pass a comparator function object as an additional
argument to the templates. For example I created

template <typename T>
struct Equal{
bool operator()(T a, T b) {return a==b;}
};

But no matter how I tried to use it, I kept getting errors saying there was
no funciton Equal(T a, T b);

This is an example:

#ifndef ARRAYCOMPARE_HH
#define ARRAYCOMPARE_HH
#include "gnuBoilerplate.hh"

#include <functional>

namespace sth{
namespace vmath{

template <typename T>
struct Equal: public std::binary_function<bool,T,T>
{
bool operator()( T a, T b) const {return a == b;}
};

template <unsigned NUMBER_OF_ELEMENTS, typename T, typename COMPARATOR>
class ArrayCompare{
public:
static bool compare(const T* a1, const T* a2)
{
return COMPARATOR(*a2, *a1)
&& ArrayCompare<NUMBER_OF_ELEMENTS - 1, T, COMPARATOR>::compare(a1 + 1,
a2 + 1);
}
};

template <typename T, typename COMPARATOR >
class ArrayCompare<1,T, COMPARATOR>{
public:
static bool compare(const T* a1, const T* a2)
{
return COMPARATOR(*a2, *a1);
}
};

template <unsigned NUMBER_OF_ELEMENTS, typename T, typename COMPARATOR >
inline bool compareArray(const T* a1, const T* a2)
{
return ArrayCompare<NUMBER_OF_ELEMENTS, T, COMPARATOR>::compare(a1,
a2);
}

}
}

#endif

/* Array2Compare.hh */
#ifndef STH_VMATH_ARRAY2COMPARE_HH_
#define STH_VMATH_ARRAY2COMPARE_HH_
#include "gnuBoilerplate.hh"

#include "ArrayCompare.hh"

#include <functional>
namespace sth{
namespace vmath{

template <unsigned NUMBER_OF_ROWS,unsigned NUMBER_OF_COLUMNS, typename
T, typename COMPARATOR >
class Array2Compare{
public:
static bool compare(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return ArrayCompare<NUMBER_OF_COLUMNS, T, COMPARATOR>::compare(a
[NUMBER_OF_ROWS-1], a2[NUMBER_OF_ROWS-1])
&& Array2Compare<NUMBER_OF_ROWS - 1, NUMBER_OF_COLUMNS, T,
COMPARATOR>::compare(a1, a2);
}
};

template <unsigned NUMBER_OF_COLUMNS, typename T, typename COMPARATOR >
class Array2Compare<1, NUMBER_OF_COLUMNS, T, COMPARATOR>{
public:
static bool compare(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return ArrayCompare<NUMBER_OF_COLUMNS, T, COMPARATOR>::compare(a1[0], a
[0]);
}
};

template<unsigned NUMBER_OF_ROWS, unsigned NUMBER_OF_COLUMNS, typename
T, typename COMPARATOR >
inline bool compare2Array(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return Array2Compare<NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, T, COMPARATOR
::compare(a1, a2); }
}
}

#endif

/* main.cc */
#include "gnuBoilerplate.hh"
#include <sth/vmath/Array2Compare.hh>
#include <iostream>

using sth::vmath::compare2Array;
using sth::vmath::Equal;

using std::cout;
using std::boolalpha;
using std::noboolalpha;
main()
{
float a1[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
float b1[3][3] = {{10,20,30},{40,50,60},{70,80,90}};
cout
<< boolalpha
<< "compare2Array(a1,b1): " << compare2Array<3,3,float,Equal<float>(a1,b1) << "\n"

<< noboolalpha;
return 0;
}
//EOF

Wed Oct 06 15:05:53:> g++ -o compare main.cc -I/home/hattons/code/c++
/home/hattons/code/c++/sth/vmath/ArrayCompare.hh:20: error: no matching
function for call to `sth::vmath::Equal<float>::Equal(const float&, const
float&)'
/home/hattons/code/c++/sth/vmath/ArrayCompare.hh:11: error: candidates are:
sth::vmath::Equal<float>::Equal()
/home/hattons/code/c++/sth/vmath/ArrayCompare.hh:11: error:
sth::vmath::Equal<float>::Equal(const sth::vmath::Equal<float>&)
Suggestions?
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell

Jul 22 '05 #1
2 1919

"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message
news:N-********************@speakeasy.net...
While thunbing through _C++ Templates, The Complete Guide_ (reckon I aught
to read it?) I came across a discussion of using templates to "unroll"
loops. I thought that looked like a good idea, so I decided to try it on
some code I'm writing. The idea is to use template objects to perform
what
happens in traditional nested for() loops.

for(int row = 0; row < num_rows; row++)
{
for(int col = 0; col < num_cols; col++)
{
operation(a1[row][col], a2[row][col]);
}
}
[snip]
I tried very hard to pass a comparator function object as an additional
argument to the templates. For example I created

template <typename T>
struct Equal{
bool operator()(T a, T b) {return a==b;}
};

But no matter how I tried to use it, I kept getting errors saying there
was
no funciton Equal(T a, T b);

I think its a simple error (but haven't tried compiling anything). I think
you are mixing object with type.

This is an example:

#ifndef ARRAYCOMPARE_HH
#define ARRAYCOMPARE_HH
#include "gnuBoilerplate.hh"

#include <functional>

namespace sth{
namespace vmath{

template <typename T>
struct Equal: public std::binary_function<bool,T,T>
{
bool operator()( T a, T b) const {return a == b;}
};

template <unsigned NUMBER_OF_ELEMENTS, typename T, typename
COMPARATOR>
class ArrayCompare{
public:
static bool compare(const T* a1, const T* a2)
{
return COMPARATOR(*a2, *a1)


COMPARATOR is a type, so you must construct an object and then call your
operator(), i.e.

return COMPARATOR()(*a2, *a1)

john
Jul 22 '05 #2
John Harrison wrote:
COMPARATOR is a type, so you must construct an object and then call your
operator(), i.e.

return COMPARATOR()(*a2, *a1)
Wow! That is SO obvious (in retrospect). I should have caught it. Thanks!

This compiles and runs, producing the expected results. I still need to
think it all through. I believe it may be traversing backwards. That's
fine for symmetrical operations, but if I want a lexicographic comparrison,
it would not perform as expected.

I did catch another stupid mistake while fixing the one you pointed out. I
now only have one call to COMPARATOR cmp; return cmp(*a2, *a1);

/* ArrayCompare.hh */
#ifndef ARRAYCOMPARE_HH
#define ARRAYCOMPARE_HH
#include "gnuBoilerplate.hh"
#include <functional>

namespace sth{
namespace vmath{

template <typename T>
struct Equal: public std::binary_function<bool,T,T>
{
bool operator()( T a, T b) const {return a == b;}
};

template <unsigned NUMBER_OF_ELEMENTS, typename T, typename COMPARATOR>
class ArrayCompare{
public:
static bool compare(const T* a1, const T* a2)
{
return ArrayCompare<1,T,COMPARATOR>::compare(a2, a1)
&& ArrayCompare<NUMBER_OF_ELEMENTS - 1, T, COMPARATOR>::compare(a1 + 1,
a2 + 1);
}
};

template <typename T, typename COMPARATOR >
class ArrayCompare<1,T, COMPARATOR>{
public:
static bool compare(const T* a1, const T* a2)
{
COMPARATOR cmp;
return cmp(*a2, *a1);
}
};

template <unsigned NUMBER_OF_ELEMENTS, typename T, typename COMPARATOR >
inline bool compareArray(const T* a1, const T* a2)
{
return ArrayCompare<NUMBER_OF_ELEMENTS, T, COMPARATOR>::compare(a1,
a2);
}

}
}

#endif
/* Array2Compare.hh */
#ifndef STH_VMATH_ARRAY2COMPARE_HH_
#define STH_VMATH_ARRAY2COMPARE_HH_
#include "ArrayCompare.hh"
#include "gnuBoilerplate.hh"

#include <functional>
namespace sth{
namespace vmath{

template <unsigned NUMBER_OF_ROWS,unsigned NUMBER_OF_COLUMNS, typename
T, typename COMPARATOR >
class Array2Compare{
public:
static bool compare(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return ArrayCompare<NUMBER_OF_COLUMNS, T, COMPARATOR>::compare(a
[NUMBER_OF_ROWS-1], a2[NUMBER_OF_ROWS-1])
&& Array2Compare<NUMBER_OF_ROWS - 1, NUMBER_OF_COLUMNS, T,
COMPARATOR>::compare(a1, a2);
}
};

template <unsigned NUMBER_OF_COLUMNS, typename T, typename COMPARATOR >
class Array2Compare<1, NUMBER_OF_COLUMNS, T, COMPARATOR>{
public:
static bool compare(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return ArrayCompare<NUMBER_OF_COLUMNS, T, COMPARATOR>::compare(a1[0], a
[0]);
}
};

template<unsigned NUMBER_OF_ROWS, unsigned NUMBER_OF_COLUMNS, typename
T, typename COMPARATOR >
inline bool compare2Array(const T a1[][NUMBER_OF_COLUMNS], const T a2[
[NUMBER_OF_COLUMNS])
{
return Array2Compare<NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, T, COMPARATOR::compare(a1, a2); }
}
}

#endif
/*main.cc*/
#include "gnuBoilerplate.hh"
#include <sth/vmath/ArrayCompare.hh>
#include <sth/vmath/Array2Compare.hh>
#include <iostream>

using sth::vmath::compareArray;
using sth::vmath::compare2Array;
using sth::vmath::Equal;

using std::cout;
using std::boolalpha;
using std::noboolalpha;
int main()
{

float a[3] = {1,2,3};
float b[3] = {10,20,30};
Equal<float> ef;
cout
<< boolalpha
<< "compareArray(a,b): " << compareArray<3,float, Equal<float> >(a,b) <<
"\n"
<< noboolalpha;
float a1[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
float a2[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
float b1[3][3] = {{10,20,30},{40,50,60},{70,80,90}};

cout
<< boolalpha
<< "compare2Array(a1,b1): " << compare2Array<3,3,float,Equal<float>(a1,b1) << "\n" << "compare2Array(a1,a2): " << compare2Array<3,3,float,Equal<float>(a1,a2) << "\n"

<< noboolalpha;

return 0;
}
/* gnuBoilerplate.hh */

#ifndef _GNU_BOILERPLATE_HH_
#define _GNU_BOILERPLATE_HH_
/************************************************** *************************
*****Copyright*(C)*2004*by*Steven*T.*Hatton******* **************************
*****ha*****@globalsymmetry.com******************* **************************
************************************************** **************************
*****This*program*is*free*software;*you*can*redist ribute*it*and/or*modify***
*****it*under*the*terms*of*the*GNU*General*Public* License*as*published*by***
*****the*Free*Software*Foundation;*either*version* 2*of*the*License,*or******
*****(at*your*option)*any*later*version.********** **************************
************************************************** **************************
*****This*program*is*distributed*in*the*hope*that* it*will*be*useful,********
*****but*WITHOUT*ANY*WARRANTY;*without*even*the*im plied*warranty*of*********
*****MERCHANTABILITY*or*FITNESS*FOR*A*PARTICULAR*P URPOSE.**See*the**********
*****GNU*General*Public*License*for*more*details.* **************************
************************************************** **************************
*****You*should*have*received*a*copy*of*the*GNU*Ge neral*Public*License******
*****along*with*this*program;*if*not,*write*to*the **************************
*****Free*Software*Foundation,*Inc.,************** **************************
*****59*Temple*Place*-*Suite*330,*Boston,*MA**02111-1307,*USA.**************
************************************************** **************************/
#endif

Now I need to generalize the code for n dimensional arrays...
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell

Jul 22 '05 #3

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

Similar topics

7
by: wogston | last post by:
A) template <typename scalar, int size> struct basevector { enum { size = size }; scalar v; }; B)
7
by: Rolf Kemper | last post by:
Dear All, somehow I remember that such or similar question was discussed already somewhere. But I can't find it anymore. I have a template...
5
by: Mohammad | last post by:
Hi, Is it possible to disable a method of a template class depending on the typename at compile time? thanks!
6
by: Hendrik Schober | last post by:
Hi, I have a problem with extending some existing code. In a simplified form, the problem looks like this: I have four types, A, B, C, and D....
6
by: Neal | last post by:
Hi All, I used an article on XSLT and XML and creating a TOC written on the MSDN CodeCorner....
5
by: Mark Stijnman | last post by:
I am trying to teach myself template metaprogramming and I have been trying to create lists of related types. I am however stuck when I want to...
19
by: n.torrey.pines | last post by:
I have the following tree definition: template<typename T> struct tree { T first; vector<tree<T second; // branches }; which compiles...
8
by: William Xu | last post by:
Compiling: template <class T = int> T foo(const T& t) {} int main(int argc, char *argv) {} gcc complains:
2
by: Clyde | last post by:
Hi, what i'm trying to do is: /////////////// Code Start template <class TType, int* p = 0> class Template { public:
0
by: concettolabs | last post by:
In today's business world, businesses are increasingly turning to PowerApps to develop custom business applications. PowerApps is a powerful tool...
0
better678
by: better678 | last post by:
Question: Discuss your understanding of the Java platform. Is the statement "Java is interpreted" correct? Answer: Java is an object-oriented...
0
by: teenabhardwaj | last post by:
How would one discover a valid source for learning news, comfort, and help for engineering designs? Covering through piles of books takes a lot of...
0
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
0
by: antdb | last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine In the overall architecture, a new "hyper-convergence" concept was...
0
by: Matthew3360 | last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function. Here is my code. ...
0
by: AndyPSV | last post by:
HOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and on my computerHOW CAN I CREATE AN AI with an .executable...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific...
0
Oralloy
by: Oralloy | last post by:
Hello Folks, I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA. My problem (spelled failure) is with the...

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.