基于条件的模板重载
Template overload based on condition
有了类型特征,我可以执行以下操作:
template<typename Rect> Rect& move(Rect& rc, size_type<Rect> delta)
{
rc.left += delta.width;
rc.right += delta.width;
rc.top += delta.height;
rc.bottom += delta.height;
return rc;
}
template<typename Rect> Rect& move(Rect& rc, point_type<Rect> to)
{
int w = w(rc);
int h = h(rc);
rc.left = to.x;
rc.top = to.y;
rc.right = rc.left + w;
rc.bottom = rc.top + h;
return rc;
}
但是我怎样才能允许在不更改函数名称的情况下传递任何大小和点类型?显然我不能这样做:
template<typename Rect, typename Size> Rect& move(Rect& rc, Size delta);
template<typename Rect, typename Point> Rect& move(Rect& rc, Point to);
我想做的是
template<typename Rect, typename Size /*if Size::width, use this*/> Rect& move(Rect& rc, Size size);
template<typename Rect, typename Point /*if Point::x, use this*/> Rect& move(Rect& rc, Point to);
即选择重载取决于模板参数是否具有特定成员。在 C++ 中可以吗?
What I want to do is
template<typename Rect, typename Size /*if Size::width, use this*/>
Rect& move(Rect& rc, Size size);
template<typename Rect, typename Point /*if Point::x, use this*/>
Rect& move(Rect& rc, Point to);
I.e. choosing an overload depends on whether a template argument has a particular member. Is it possible in c++?
如果您至少可以使用 C++11...您是否通过尾随 return 类型和 decltype()
尝试使用 SFINAE?
我的意思是……
template <typename Rect, typename Size>
auto move (Rect & rc, Size size)
-> decltype( size.width, rc );
// .............^^^^^^^^^^^ <-- note this
template <typename Rect, typename Point>
auto move(Rect& rc, Point to)
-> decltype( to.x, rc );
// .............^^^^^ <-- and note this
显然,如果您使用带有 with
和 x
成员的第二个参数调用 move()
,这显然不起作用:编译器不知道哪个 move()
select.
它是如何工作的?
很简单:主词是SFINAE,意思是Substitution Failure Is Not An Error。
考虑 decltype()
return 包含的表达式的类型,因此(例如)来自
decltype( size.width, rc );
逗号运算符丢弃 size.width
、if available(这是重点!),并保留 rc
,所以 decltype()
return rc
的类型(如果 size.width
存在!)。
但是如果 size.width
不存在会怎样?
您遇到了“替换失败”。那“不是错误”,而是从可用的 move()
函数集中删除 move()
的这个重载版本。
有了类型特征,我可以执行以下操作:
template<typename Rect> Rect& move(Rect& rc, size_type<Rect> delta)
{
rc.left += delta.width;
rc.right += delta.width;
rc.top += delta.height;
rc.bottom += delta.height;
return rc;
}
template<typename Rect> Rect& move(Rect& rc, point_type<Rect> to)
{
int w = w(rc);
int h = h(rc);
rc.left = to.x;
rc.top = to.y;
rc.right = rc.left + w;
rc.bottom = rc.top + h;
return rc;
}
但是我怎样才能允许在不更改函数名称的情况下传递任何大小和点类型?显然我不能这样做:
template<typename Rect, typename Size> Rect& move(Rect& rc, Size delta);
template<typename Rect, typename Point> Rect& move(Rect& rc, Point to);
我想做的是
template<typename Rect, typename Size /*if Size::width, use this*/> Rect& move(Rect& rc, Size size);
template<typename Rect, typename Point /*if Point::x, use this*/> Rect& move(Rect& rc, Point to);
即选择重载取决于模板参数是否具有特定成员。在 C++ 中可以吗?
What I want to do is
template<typename Rect, typename Size /*if Size::width, use this*/> Rect& move(Rect& rc, Size size);
template<typename Rect, typename Point /*if Point::x, use this*/> Rect& move(Rect& rc, Point to);
I.e. choosing an overload depends on whether a template argument has a particular member. Is it possible in c++?
如果您至少可以使用 C++11...您是否通过尾随 return 类型和 decltype()
尝试使用 SFINAE?
我的意思是……
template <typename Rect, typename Size>
auto move (Rect & rc, Size size)
-> decltype( size.width, rc );
// .............^^^^^^^^^^^ <-- note this
template <typename Rect, typename Point>
auto move(Rect& rc, Point to)
-> decltype( to.x, rc );
// .............^^^^^ <-- and note this
显然,如果您使用带有 with
和 x
成员的第二个参数调用 move()
,这显然不起作用:编译器不知道哪个 move()
select.
它是如何工作的?
很简单:主词是SFINAE,意思是Substitution Failure Is Not An Error。
考虑 decltype()
return 包含的表达式的类型,因此(例如)来自
decltype( size.width, rc );
逗号运算符丢弃 size.width
、if available(这是重点!),并保留 rc
,所以 decltype()
return rc
的类型(如果 size.width
存在!)。
但是如果 size.width
不存在会怎样?
您遇到了“替换失败”。那“不是错误”,而是从可用的 move()
函数集中删除 move()
的这个重载版本。