Template query

Nov 6, 2010 at 6:21am
Here's something interesting which i ran into recently. Look at the code below.

1
2
3
4
5
6
7
8
9
10
11
12
template <class T>
class A{
        public:
                A(const T& v){}
                A(const T *ptr){}
};

int main(){
         A<double> a(0); // This call is ambiguous
         A<double> a(1); // this works just fine. 
}


As i understood this, 0 can be assigned directly to a double variable or a
pointer and hence the call is ambiguous and the code does not compile. Is there
anyway around this ? I can always use A<double> a(0.0) and the problem goes away
But i would still like to know if there is any way to avoid what i am seeing
here.

Thanks.
Nov 6, 2010 at 7:40am
i would still like to know if there is any way to avoid what i am seeing
here.
A<double> a(0.0)
That is it.
Nov 6, 2010 at 4:54pm
I would eliminate the second constructor. It's only benefit is to allow the to avoid having to dereference something him/herself. eg.

1
2
3
4
5
6
int main() {
    double* pi = new double( 3.14 );

    A<double> a( *pi );  // Calls the first constructor
    A<double> a( pi );    // Calls the second
}

Nov 8, 2010 at 1:52am
@jsmith

The template is my implementation of a vector class. So both the constructors do different things. a(const T& v) sets each element of the entire vector to v and a(const T *ptr) copies the values of the array ptr into the the vector.

its not a severe problem though. I can live with it.
Nov 8, 2010 at 2:35am
a(const T *ptr) copies the values of the array ptr into the the vector
How do you know how long the array is?
Nov 8, 2010 at 4:21am
good point. So, the vector class knows how many elements of the input array to copy. The input array has to be at least the length of the vector but can be more. If the size of the input array is less than that of vector, the code fails. This was just a design choice.
Nov 8, 2010 at 5:11am
A very poor one. You should be passing the size of the array. That will also take care of the ambiguity.
Nov 8, 2010 at 6:10am
:) Hardly.

the structure is like this. Class A -> Class B - > Class C.

Class A is just a contiguous block of data. Class B decides where A should be interpreted as a vector or a matrix. User is forced to specify size with all constructors of A and B. Class C is very small and has fixed length and essentially consists just of calling appropriate constructors of class B. The names of class C are sufficiently indicative of the length/dimension. e.g. it could be like Mat44 or Vec4. I think it is fair to assume that a user attempting to define a Vec4 will give an input array of atleast length 4.

The initialization is just for convenience and not central to anything in the rest of the code. So perhaps I will just get rid of the constructor with pointer.
Nov 8, 2010 at 3:08pm
You should not assume that the user will get it right.

If A is essentially a fixed length vector (fixed at compile time, it must be, otherwise your constructor can't know
how long the array is), then write the constructor as

 
A( T (const &a)[ 1024 ] )   // replace 1024 with whatever the fixed length array is 


and now the constructor can ONLY be called with a fixed length array that is exactly 1024 elements.

Nov 8, 2010 at 3:23pm
+1 jsmith and helios
Topic archived. No new replies allowed.