C++ (more specifically, MinGW's implementation of g++) is getting confused. I have a mathematical Vector class that contains an arbitrary number of an arbitrary type of element. The element type and number of elements are specified at compile time.
The Vector class is getting confused between one of it's constructors and what I have dubbed the "resize" operator. The resize operator allows the programmer to cast a vector of one size into a vector of another arbitrary size. If the cast vector has more elements than the base vector, it pads with 1's. Here's the implementation:
/*
* resize operator:
* T is the type of element the base vector holds
* N is the number of elements the base vector holds
* rN is the size of the new vector
*/
template<typename T, unsigned int N, unsigned int rN>
operator Vector<T, rN>() const
{
Vector<T, rN> resize;
for (unsigned int i = 0; i < rN; i++)
{
resize[i] = i < N ? this->elements[i] : 1;
}
return resize;
}
The vector class also has a type-safe variadic constructor that can take any number of any combinations of elements (which must be of type T) and any number of Vectors (which can contain any number of elements and must be of type T) so long as the number of bare elements added to the number of elements in the supplied vectors is equal to the number of elements that the constructing vector contains.
Thus this would be valid:
vec3 foo(vec2(1, 2), 3);
but not this.
vec3 bar(vec4(1, 2, 3, 4), 5);
I ensure that the proper number of elements has been supplied at compile time by recursing through them all with a counter, then I use a static assertion to make sure the counter ends up at number of elements the vector can contain. This normally works out well, except for the following code:
vec4 bar(1, 2, 3, 4);
(vec3) bar; //PROBLEM HERE
What's happening is that the C++ thinks that (vec3) bar is asking for the variadic constructor when, in fact, it should be calling the resize operator. I've tried making them explicit, but it hasn't worked. How do I ensure that C++ uses the resize operator when I have the above code and not the variadic constructor?
In short, how do I tell C++ to use this:
//resize operator
template<typename T, unsigned int N, unsigned int rN>
Vector<T, N>::operator Vector<T, rN>();
instead of this:
//constructor
template<typename T, unsigned int N, typename ... Args>
Vector<T, N>::Vector(Args ... arguments);
when I have this code:
(vec3) someVec4;
In case it wasn't clear, vec3 and vec4 are defined as such:
typedef Vector<float, 3> vec3;
typedef Vector<float, 4> vec4;
EDIT:
News, everyone! Even when I use static_cast(someVec4) it still calls the vec3 constructor with a vec4 argument. I don't know why.
ANOTHER EDIT:
Making the constructor explicit allows implicit casts to work, but not explicit ones. Which is to say that this code works:
vec3 foo = someVec4;
But this code still gives me a static assertion failure:
vec3 foo = static_cast<vec3>(someVec4);
Which makes basically no sense because I declared the variadic constructor explicit, and thus it shouldn't be called there.
Also, upon request, here's an SSCCE
The TL;DR version of this is that my code is calling an explicit constructor when I try to explicitly call the typecasting operator, but not when I try to implicitly call it.
I think the simplest was to get your code working is to replace the conversion operator by a conversion constructor. Since that constructor is more specialized than the variadic constructor, it should always take precedence.