Code
#include <type_traits>
template <typename N>
concept Number = std::is_arithmetic<N>::value;
template <typename T>
concept VectorXY = requires(T t)
{
{t.x} -> Number;
{t.y} -> Number;
};
template <Number N>
struct Vec2
{
N x = 0;
N y = 0;
};
VectorXY operator*(VectorXY v, Number n)
{
return {v.x * n, v.y * n};
// error: returning initializer list
}
int main()
{
Vec2<float> v = Vec2<float>{} * 1;
// error: conversion from 'void' to non-scalar type 'Vec2<float>' requested
}
Godbolt: https://godbolt.org/z/gYsQ5B
So how do I solve this?
An explanation as to why the compiler can't infer the return type would be helpful as well.
VectorXY is not a type. It's a concept that's meant to check the type deduced from expression you return from the function. And said type deduction is entirely separate from deducing the type of the function's parameter.
What you return is
{v.x * n, v.y * n}
It's a braced enclosed initializer. When doing template argument deduction against it, what normally gets deduced is a std::initializer_list. The two problems with that is that first, the corresponding header is not included, so the program is ill-formed. And secondly, even if the header was included, std::initializer_list<float> does not satisfy the VectorXY concept.
You can fix it by specifying the type of the returned object, for instance via functional cast notation
return decltype(v){v.x * n, v.y * n};
Now it's a typed expression, against which the function's return type is deduced to something that satisfies the VectorXY concept.
Live Example.
As an addendum, GCC doesn't implement it yet, but the correct syntax should be
VectorXY auto operator*(VectorXY auto v, Number auto n)
{
return decltype(v){v.x * n, v.y * n};
}
Given the confusion that stems from just using VectorXY, I think the committee was right to require this constrained auto syntax instead. The fact there is a type deduction going on is more obvious to me here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With