I have the template struct
template <class T>
struct Vector2
{
T x, y;
};
with the following function overloading the + operator
template <typename T1, typename T2>
Vector2 operator+(const Vector2<T1>& v1, const Vector2<T2>& v2)
{
auto x = v1.x + v2.x;
auto y = v1.y + v2.y;
Vector2 result{ x, y };
return result;
}
I get the error argument list for class template "Vector2" is missing
, which I understand why as the return type doesnt supply a type for the template. My issue is I want the return type to change. If both arguments are Vector2 then the return type should be a Vector2. However, if one of the arguments is a Vector2, the return type should be promoted to a Vector2.
I attempted to use auto so that when I create the variable result, it would be converted correctly and the Vector2 wouldnt need a template argument. I know this should work as
Vector2 vectorInt = { 3, 2 };
Vector2 vectorDouble = { 1.4,4.4 };
both work correctly. The main issue is the return type on the function itself.
I understand I am probably not doing things right as I am curretly new to learning C++ from from my knowledge in other languages.
What I want to know is, is this even possible and if so, how?
> Vector2 vectorInt = { 3, 2 };
> Vector2 vectorDouble = { 1.4,4.4 };
This constructions use CTAD. The compiler determines template arguments from types of provided initializers.
But there is no way for the compiler to find out template arguments from function declaration or definition. You can use auto
return type instead:
template <typename T1, typename T2>
auto operator+(const Vector2<T1>& v1, const Vector2<T2>& v2)
{
auto x = v1.x + v2.x;
auto y = v1.y + v2.y;
return Vector2{ x, y };
};
But that might not be sufficient if you want to check the return type in constraint templates.So, You can be more verbose by trailing return types:
template <typename T1, typename T2>
auto operator+(const Vector2<T1>& v1, const Vector2<T2>& v2)
-> Vector2<decltype(v1.x + v2.x)>
{
auto x = v1.x + v2.x;
auto y = v1.y + v2.y;
return { x, y };
};
Or use the old style return type:
template <typename T1, typename T2>
Vector2<decltype(std::declval<T1>() + std::declval<T2>())>
operator+(const Vector2<T1>& v1, const Vector2<T2>& v2)
{
auto x = v1.x + v2.x;
auto y = v1.y + v2.y;
return { x, y };
};
In the above snippets you can replace the decltype(...)
expressions with std::common_type_t<T1,T2>
as well. But I prefer the decltype
version for accuracy.