Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > argument deduction for function template

Reply
Thread Tools

argument deduction for function template

 
 
vectorizor
Guest
Posts: n/a
 
      06-21-2007
Hi all,

I have a slight problem with the usage of function templates. It shoud
be really easy for you guys to explain me what's wrong.

I have one base class and 2 derived classes:

/*code*/
template <typename T> struct Image {...};
template <typename T> struct GrayImage : public Image<T> {...};
template <typename T> struct ColorImage : public Image<T> {...};
/*code*/

I am now trying to write a funtion to process images. The definition
is:

/*code*/
template <typename T, typename U> void func1(ColourImage<U> &input,
GrayImage<T> &output) {...}
/*code*/

Now I am tring to call this function as follow

/*code*/
GrayImage<f32> gray, tmp;
ColourImage<u8> color;
// ....
func1(color, gray);
/*code*/

When I try to compile that, the Visual Studio compilers complains that
"template parameter 'T' is ambiguous". Why is that? I do not
understand why.
It works though if I specify the template arguments explicitly though,
as follow

/*code*/
func1<f32, u8>(color, gray);
/*code*/

But ideally, I would like not to specify that. The thing that really
puzzles me is that I do not need to do that for a very similar
function.

/*code*/
template <typename T> void test(GrayImage<T> &input, GrayImage<T>
&output) {...}
// ...
GrayImage<f32> gray, tmp;
// ...
test(gray, tmp);
/*code*/

This works just fine. So what is the problem with the previous
function?!

Thanks in advance

Alex

 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      06-21-2007
vectorizor wrote:
> Hi all,
>
> I have a slight problem with the usage of function templates. It shoud
> be really easy for you guys to explain me what's wrong.
>
> I have one base class and 2 derived classes:
>
> /*code*/
> template <typename T> struct Image {...};
> template <typename T> struct GrayImage : public Image<T> {...};
> template <typename T> struct ColorImage : public Image<T> {...};


Note the spelling of 'ColorImage'.

> /*code*/
>
> I am now trying to write a funtion to process images. The definition
> is:
>
> /*code*/
> template <typename T, typename U> void func1(ColourImage<U> &input,


Note the spelling of the type of the first argument.

> GrayImage<T> &output) {...}
> /*code*/
>
> Now I am tring to call this function as follow
>
> /*code*/
> GrayImage<f32> gray, tmp;
> ColourImage<u8> color;


Not the spelling of the type and the variable here. Please try to
stick to naming your things _consistently_.

This goes again toward the argument why code should NOT be typed into
the message. *Copy and paste* your code!!!

> // ....
> func1(color, gray);
> /*code*/
>
> When I try to compile that, the Visual Studio compilers


Which ones? VC++ 2005 seems to compile it correctly.

> complains that
> "template parameter 'T' is ambiguous". Why is that? I do not
> understand why.


Because the compiler[s] you're using is/are buggy?

> It works though if I specify the template arguments explicitly though,
> as follow
>
> /*code*/
> func1<f32, u8>(color, gray);
> /*code*/
>
> But ideally, I would like not to specify that. The thing that really
> puzzles me is that I do not need to do that for a very similar
> function.
>
> /*code*/
> template <typename T> void test(GrayImage<T> &input, GrayImage<T>
> &output) {...}
> // ...
> GrayImage<f32> gray, tmp;
> // ...
> test(gray, tmp);
> /*code*/
>
> This works just fine. So what is the problem with the previous
> function?!


No problem. But if you have to use the compiler[s] you are using,
stick to your work-around.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
 
 
 
Zeppe
Guest
Posts: n/a
 
      06-21-2007
Victor Bazarov wrote:
> vectorizor wrote:
>> complains that
>> "template parameter 'T' is ambiguous". Why is that? I do not
>> understand why.

>
> Because the compiler[s] you're using is/are buggy?
>


I would guess that the code he compiled is not the same that the one in
the message.

Regards,

Zeppe

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      06-21-2007
Zeppe wrote:
> Victor Bazarov wrote:
>> vectorizor wrote:
>>> complains that
>>> "template parameter 'T' is ambiguous". Why is that? I do not
>>> understand why.

>>
>> Because the compiler[s] you're using is/are buggy?
>>

>
> I would guess that the code he compiled is not the same that the one
> in the message.


That's a pretty good guess. But it might also be true that the OP's
not using the latest compiler, and as I recall, VC++ v6 was *really*
bad with templates. VC++ v7.0 wasn't to much better either. The
break came at VC++ v7.1. I have no way of testing *my* interpretation
of the OP's code with any of those at this point.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
=?ISO-8859-1?Q?Erik_Wikstr=F6m?=
Guest
Posts: n/a
 
      06-21-2007
On 2007-06-21 16:14, vectorizor wrote:
> Hi all,
>
> I have a slight problem with the usage of function templates. It shoud
> be really easy for you guys to explain me what's wrong.
>
> I have one base class and 2 derived classes:
>
> /*code*/
> template <typename T> struct Image {...};
> template <typename T> struct GrayImage : public Image<T> {...};
> template <typename T> struct ColorImage : public Image<T> {...};
> /*code*/
>
> I am now trying to write a funtion to process images. The definition
> is:
>
> /*code*/
> template <typename T, typename U> void func1(ColourImage<U> &input,
> GrayImage<T> &output) {...}
> /*code*/
>
> Now I am tring to call this function as follow
>
> /*code*/
> GrayImage<f32> gray, tmp;
> ColourImage<u8> color;
> // ....
> func1(color, gray);
> /*code*/
>
> When I try to compile that, the Visual Studio compilers complains that
> "template parameter 'T' is ambiguous". Why is that? I do not
> understand why.
> It works though if I specify the template arguments explicitly though,
> as follow
>
> /*code*/
> func1<f32, u8>(color, gray);
> /*code*/
>
> But ideally, I would like not to specify that. The thing that really
> puzzles me is that I do not need to do that for a very similar
> function.
>
> /*code*/
> template <typename T> void test(GrayImage<T> &input, GrayImage<T>
> &output) {...}
> // ...
> GrayImage<f32> gray, tmp;
> // ...
> test(gray, tmp);
> /*code*/
>
> This works just fine. So what is the problem with the previous
> function?!


Except from some ambiguity whether it's called ColourImage or ColorImage
I could find no problems and ended up with the following code from your
snippets above:

template <typename T>
struct Image
{ };

template <typename T>
struct GrayImage : public Image<T>
{ };

template <typename T>
struct ColorImage : public Image<T>
{ };

template <typename T, typename U>
void func1(ColorImage<U> &input, GrayImage<T> &output)
{ }

int main()
{
GrayImage<float> gray;
ColorImage<int> color;
func1(color, gray);
}

This compiles fine with both VC++2005 and Comeau online. Did I miss
something or is there some code you have not shown us? By the way, which
compiler are you using?

--
Erik Wikström
 
Reply With Quote
 
vectorizor
Guest
Posts: n/a
 
      06-21-2007
Hey all,

thanks for the comments. Please find attached a standalone version of
my code. Please forgive the mess, I just did a quick copy and paste of
many files.

I am compiling with VS 2005 and the latest Intel compiler.

##### CUT #####
#include <windows.h>
#include <stdio.h>
#include <math.h>

////////////////////
///// INTEGERS
////////////////////

// unsigned
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef unsigned long long u64;

// signed
typedef signed char i8;
typedef signed short i16;
typedef signed long i32;
typedef signed long long i64;




////////////////////
///// FLOATING-POINT VALUES
////////////////////

typedef float f32;
typedef double f64;




////////////////////
///// MEMORY ROUTINES
////////////////////

enum { MemoryAlignment=64};

void* AllocateMemory(size_t size)
{
return _aligned_malloc(size, MemoryAlignment);
}

void ReleaseMemory(void *memblock)
{
return _aligned_free(memblock);
}

int ComputeAlignedWidth(int width)
{
int alignment_needed = MemoryAlignment / sizeof(float);
return (int)ceil((float)width/(float)alignment_needed) *
alignment_needed;
}




////////////////////
///// CLASS DECLARATION
////////////////////


template <typename T>
struct Image
{
public: // members
// std information
int width, height, depth;

// actual width of the buffer
// buffer holding image data is padded to be a multiple
// of MemoryAlignment for optimisation purposes
int width_padded;

// dimensions helper
int firstRow, lastRow, firstCol, lastCol;

// pointer to the image data
T* data;

public: // methods
// ctor
Image():
width(0),height(0),depth(0),
width_padded(0),
firstRow(0), lastRow(0), firstCol(0), lastCol(0),
data(NULL)
{
}

// dtor
~Image()
{
}

// memory management
void Allocate() { data =
static_cast<T*>(AllocateMemory(width_padded*height *depth*sizeof(T)));}
void Release () { ReleaseMemory(data);}

// pixel access
// virtual T& operator() (int row, int col)

// dimensions management
void SetDimensions(int h, int w, int d){
height = h;
width = w;
depth = d;
width_padded = ComputeAlignedWidth(width);
firstRow = 0;
firstCol = 0;
lastRow = height-1;
lastCol = width-1;
}

// size information
int GetTotalSize(bool padded=false){
if (padded) return width_padded*height*depth*sizeof(T);
else return width *height*depth*sizeof(T);
}
int GetImageSize(bool padded=false){
if (padded) return width_padded*height*depth;
else return width *height*depth;
}
int GetPlaneSize(bool padded=false){
if (padded) return width_padded*height;
else return width *height;
}

};




template <typename T>
struct GrayImage : public Image<T>
{
public: // methods
// ctor
GrayImage():
Image()
{
depth=1;
}

// pixel access
T& operator() (int row, int col)
{
return data[row*width_padded + col];
}
};




template <typename T>
struct ColourImage : public Image<T>
{
public: // definitions

enum{red=0, green=1, blue=2};
enum{r =0, g =1, b =2};

public: // methods
// ctor
ColourImage():
Image()
{
depth=3;
}

// pixel access
T& operator() (int row, int col, int channel)
{
return data[(row*width_padded + col)*3 + channel];
}
};



#define MIN(A,B) ((A < B) ? A : B)
#define MAX(A,B) ((A > B) ? A : B)
#define MAX3(R, G, B) ((((R) > (G) ? (R) : (G)) > B) ? ((R) > (G) ?
(R) : (G)) : B)


template <typename T, typename U>
void RGB2Log(ColourImage<U> &input, GrayImage<T> &buffer, bool linear,
T snr)
{
for(int row=input.firstRow ; row<=input.lastRow ; ++row){
for(int col=input.firstCol ; col<input.lastCol; ++col){
buffer(row, col) = MAX3(input(row, col,
ColourImage<U>::r),
input(row, col,
ColourImage<U>::g),
input(row, col,
ColourImage<U>::b));

}
}

return;
}

template <typename T>
void test(GrayImage<T> &input, GrayImage<T> &output)
{
for(int row=input.firstRow ; row<=input.lastRow ; ++row){
for(int col=input.firstCol ; col<input.lastCol; ++col){
output(row, col) = input(row, col)/2;
}
}
}




int main(int argc, char* argv[])
{
GrayImage<f32> gray, tmp;
ColourImage<u8> color;

gray.SetDimensions(2000, 2000, 3); gray.Allocate();
color.Allocate();
gray.SetDimensions(color.height, color.width, 1);
gray.Allocate();
tmp.SetDimensions(color.height, color.width, 1);
tmp.Allocate();

RGB2Log(color, gray, true, 1.0);
//RGB2Log<f32, u8>(color, gray, true, 1.0);

test(gray, tmp);

color.Release(); gray.Release(); tmp.Release();

return 0;
}

##### CUT #####

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      06-21-2007
vectorizor wrote:
> Hey all,
>
> thanks for the comments. Please find attached a standalone version of
> my code. Please forgive the mess, I just did a quick copy and paste of
> many files.
>
> I am compiling with VS 2005 and the latest Intel compiler.


This is what your code should look like, distilled:

>
> [..]
> typedef float f32;
> typedef unsigned char u8;
>
> template <typename T>
> struct Image
> {
> };
>
> template <typename T>
> struct GrayImage : public Image<T>
> {
> };
>
> template <typename T>
> struct ColourImage : public Image<T>
> {
> };
>
> template <typename T, typename U>
> void RGB2Log(ColourImage<U> &input, GrayImage<T> &buffer,
> bool linear, T snr)
> {
> }
>
> int main(int argc, char* argv[])
> {
> GrayImage<f32> gray, tmp;
> ColourImage<u8> color;
>
> RGB2Log(color, gray, true, 1.0);


Here you pass 'GrayImage<f32>' as the second argument from which
'T' is deduced as 'f32' or 'float'. _And_ you pass 1.0 (a double
literal) as the fourth argument, from which 'T' is deduced as...
'double' ! Do you not see it in the error message?

Now , if you want '1.0' to be treated as 'f32', you need to cast
it to 'f32':

RGB2Log(color, gray, true, (f32) 1.0);

> }
>
> ##### CUT #####


V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
vectorizor
Guest
Posts: n/a
 
      06-21-2007
Thanks a lot, and well spotted! I really couldn't understand, so I was
half-expecting something silly like that, but I just couldnt see it!

> Do you not see it in the error message?


no, both compilers just mentioned they cowardly gave up!

Thanks again,

Alex

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      06-21-2007
vectorizor wrote:
> Thanks a lot, and well spotted! I really couldn't understand, so I was
> half-expecting something silly like that, but I just couldnt see it!
>
>> Do you not see it in the error message?

>
> no, both compilers just mentioned they cowardly gave up!


You need a better compiler. VC++ 2005 gave something in line with
"Ambiguous template argument T, can be f32 or double".

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
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
Template argument deduction and function pointers Tobias Müller C++ 12 12-15-2011 10:53 PM
Template argument deduction cannot be performed George C++ 4 01-13-2006 12:15 AM
Template argument deduction on integer literals Bart Samwel C++ 14 04-22-2005 10:03 PM
Template argument deduction Peng Yu C++ 1 04-16-2005 04:30 PM
Template argument deduction and conversion operators. BigMan@abv.bg C++ 3 02-02-2005 09:15 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