Template deduction fails when using conversion operator but explicit casting works

92 Views Asked by At

I'm trying to implement swizzle vectors in C++ with template programming. With swizzle vectors I mean vectors similar to hlsl and glsl vectors where for example if you have a vector v = (1,2,3,4) and do v.xxyz it produces the vector (1,1,2,3).

This involves a data structure that is similar to the example presented below however I removed a bunch of stuff to produce a minimal working example.

#include <iostream>
template <typename T>
class vec2
{
public:
    template<unsigned a, unsigned b>
    class swizzle
    {
    public:
        T v[2];
    public:
        operator vec2() { return { v[a], v[b] }; }
    };

public:
    union
    {
        struct
        {
            T x, y;
        };
        swizzle<0, 0> xx;
        swizzle<0, 1> xy;
        swizzle<1, 0> yx;
        swizzle<1, 1> yy;
        T v[2];
    };
};

template<typename T>
void Foo(const vec2<T>& bar)
{
    std::cout << bar.x << ", " << bar.y << "\n";
}

void Bar(const vec2<float> bar)
{
    std::cout << bar.x << ", " << bar.y << "\n";
}

int main()
{
    vec2<float> v = { 1,2 };
    Foo(v.xx); //Does not compile. Template argument deduction fails.

    Foo((vec2<float>)v.xx); //Compiles. Prints "1, 1"

    Foo(v); //Compiles . Prints "1, 2"

    Bar(v.xx); //Compiles without having to explicitly cast it. Prints "1, 1"
    std::cin.get();
    return 0;
}

In the above example the call to Foo with an argument of type swizzle does not compile unless I explicitly cast the swizzle to a vec2<float> even though swizzle has a conversion operator. Does implicit conversion not work when dealing with templates? My problem here is that I would like to be able to call Foo with both Foo(v) as well as Foo(v.xy).

0

There are 0 best solutions below