Template query

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.
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.
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
}

@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.
a(const T *ptr) copies the values of the array ptr into the the vector
How do you know how long the array is?
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.
A very poor one. You should be passing the size of the array. That will also take care of the ambiguity.
:) 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.
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.

+1 jsmith and helios
Topic archived. No new replies allowed.