Template instantiation problem

K

Kaba

Here is a short snippet of code that does not compile (tested with Vc8
and Comeau). This is because somehow Vector<0> gets instantiated, for
which the array size goes to 0. However, I don't quite get it why it
gets instantiated in the first place. So why does not this compile?

template <int N>
struct Vector
{
int data_[N];
};

template <int HEIGHT, int WIDTH>
struct Matrix
{
};

template <int HEIGHT, int WIDTH>
Vector<WIDTH> operator *(
const Vector<HEIGHT>&,
const Matrix<HEIGHT, WIDTH>&)
{
return Vector<WIDTH>();
}

template <int HEIGHT, int WIDTH>
Vector<WIDTH - 1> operator *(
const Vector<HEIGHT - 1>&,
const Matrix<HEIGHT, WIDTH>&)
{
return Vector<WIDTH - 1>();
}

int main()
{
Matrix<1, 1> transform;
Vector<1> translation;

translation = translation * transform;

return 0;
}
 
A

amparikh

Kaba said:
Here is a short snippet of code that does not compile (tested with Vc8
and Comeau). This is because somehow Vector<0> gets instantiated, for
which the array size goes to 0. However, I don't quite get it why it
gets instantiated in the first place. So why does not this compile?

template <int N>
struct Vector
{
int data_[N];
};

template <int HEIGHT, int WIDTH>
struct Matrix
{
};

template <int HEIGHT, int WIDTH>
Vector<WIDTH> operator *(
const Vector<HEIGHT>&,
const Matrix<HEIGHT, WIDTH>&)
{
return Vector<WIDTH>();
}

template <int HEIGHT, int WIDTH>
Vector<WIDTH - 1> operator *(
const Vector<HEIGHT - 1>&,
const Matrix<HEIGHT, WIDTH>&)
{
return Vector<WIDTH - 1>();
}

int main()
{
Matrix<1, 1> transform;
Vector<1> translation;

translation = translation * transform;

return 0;
}


what do you think the following line instantiates from your given
example ?
return Vector<WIDTH - 1>();
 
K

Kaba

what do you think the following line instantiates from your given
example ?
return Vector<WIDTH - 1>();

Right, but a template is only instantiated when used, and I am not using
that template function (but the other). The question is: why would that
function be instantiated?
 
G

Greg

Kaba said:
Right, but a template is only instantiated when used, and I am not using
that template function (but the other). The question is: why would that
function be instantiated?

Both operator*() functions are instantiated while the compiler is
resolving which function the expression "translation * transform" is to
call.

A simple fix would be to specialize Vector<0>:

template <>
struct Vector<0>
{
};

Greg
 
K

Kaba

Both operator*() functions are instantiated while the compiler is
resolving which function the expression "translation * transform" is to
call.

Hmm.. Yes, sounds reasonable. So the 0-array declaration here does not
go under SFINAE?
A simple fix would be to specialize Vector<0>:

template <>
struct Vector<0>
{
};

Right.
 
G

Greg

Kaba said:
Hmm.. Yes, sounds reasonable. So the 0-array declaration here does not
go under SFINAE?

The failure is an instantiation failure that comes before the
substitution can even be attempted. Once vector<0> is instantiable
(say, by providing a specialization) then the substitution does fail
without an error.

Greg
 
K

Kaba

Hmm.. Yes, sounds reasonable. So the 0-array declaration here does not
The failure is an instantiation failure that comes before the
substitution can even be attempted. Once vector<0> is instantiable
(say, by providing a specialization) then the substitution does fail
without an error.

I am still not convinced. Let's take another try.. I simplified the
problem:

template <int N>
struct Vector
{
int data_[N];
};

template <int N>
struct Matrix
{
};

template <int N>
int operator *(
const Vector<N>&,
const Matrix<N>&)
{
return 0;
}

template <int N>
int operator *(
const Vector<N - 1>&,
const Matrix<N>&)
{
return 1;
}

int main()
{
Matrix<1> transform;
Vector<1> translation;

int result = translation * transform;

return 0;
}

If I were a compiler I would act like this:

1) If in the first function I take the Matrix<1> to conclude N = 1, then
the other parameter is Vector<1> and we have a match.

2) If in the first function I take the Vector<1> to conclude N = 1, then
the other parameter is Matrix<1> and we have a match.

3) If in the second function I take the Matrix<1> to conclude N = 1,
then the other parameter is Vector<0> and we don't have a match.

4) If in the second function I take the Vector<1> to conclude N = 2,
then the other parameter is Matrix<2> and we don't have a match.

Thus, without ever needing instantiation of any template, we have
concluded that the first function is the only possible candidate. Why
would the compiler need the instantiation of Vector<0> or Matrix<2>?

Btw, I reposted this question to comp.lang.c++.moderated before you
replied this second time. I thought there will be no more replies
because this newsgroup has such a traffic all the time. The comment I
make there is written before you replied, so it is not to say that you
couldn't deliver the answer.

Anyway, you still haven't convinced me of the reasons which lead to the
instantion of Vector<0>.. Examples showing its necessity and/or relevant
quotes from the standard would help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,430
Messages
2,571,676
Members
48,796
Latest member
Greg L.

Latest Threads

Top