从使用概念定义的函数返回新对象
Returning new object from function defined using Concepts
代码
#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
}
神马:https://godbolt.org/z/gYsQ5B
那我该如何解决呢?
关于编译器为何无法推断 return 类型的解释也会有所帮助。
VectorXY
不是类型。这是一个概念,旨在检查从函数中 return 表达式推导出的类型。并且所述类型推导完全独立于推导函数的 参数 .
的类型
你return是什么
{v.x * n, v.y * n}
这是一个花括号封闭的初始化器。当对其进行模板参数推导时,通常推导的是 std::initializer_list
。这样做的两个问题是,第一,没有包含相应的 header,所以程序是 ill-formed。其次,即使 header 被 包括在内,std::initializer_list<float>
也不满足 VectorXY
概念。
您可以通过指定 returned object 的类型来修复它,例如通过功能转换符号
return decltype(v){v.x * n, v.y * n};
现在它是一个类型化的表达式,根据它函数的 return 类型被推断为满足 VectorXY
概念的东西。
作为附录,GCC 还没有实现它,但正确的语法应该是
VectorXY auto operator*(VectorXY auto v, Number auto n)
{
return decltype(v){v.x * n, v.y * n};
}
鉴于仅使用 VectorXY
引起的混淆,我认为委员会要求使用这种受约束的 auto
语法是正确的。类型推导的事实在这里对我来说更为明显。
代码
#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
}
神马:https://godbolt.org/z/gYsQ5B
那我该如何解决呢?
关于编译器为何无法推断 return 类型的解释也会有所帮助。
VectorXY
不是类型。这是一个概念,旨在检查从函数中 return 表达式推导出的类型。并且所述类型推导完全独立于推导函数的 参数 .
你return是什么
{v.x * n, v.y * n}
这是一个花括号封闭的初始化器。当对其进行模板参数推导时,通常推导的是 std::initializer_list
。这样做的两个问题是,第一,没有包含相应的 header,所以程序是 ill-formed。其次,即使 header 被 包括在内,std::initializer_list<float>
也不满足 VectorXY
概念。
您可以通过指定 returned object 的类型来修复它,例如通过功能转换符号
return decltype(v){v.x * n, v.y * n};
现在它是一个类型化的表达式,根据它函数的 return 类型被推断为满足 VectorXY
概念的东西。
作为附录,GCC 还没有实现它,但正确的语法应该是
VectorXY auto operator*(VectorXY auto v, Number auto n)
{
return decltype(v){v.x * n, v.y * n};
}
鉴于仅使用 VectorXY
引起的混淆,我认为委员会要求使用这种受约束的 auto
语法是正确的。类型推导的事实在这里对我来说更为明显。