我正在尝试创建一个在提供成员函数Y时专门化的函数X,并且如果未提供成员函数Y,则函数X使用全局非成员函数Y来实现相同的效果。
我目前正尝试使用以下代码实现此目的
template <typename Container, typename std::enable_if_t<std::is_same<
decltype(std::declval<Container>().y()),
decltype(std::declval<Container>().y())>::value>* = nullptr>
void do_something(Container&& container) {
return std::forward<Container>().y();
}
template <typename Container, typename std::enable_if_t<!std::is_same<
decltype(std::declval<Container>().y()),
decltype(std::declval<Container>().y())>::value>* = nullptr>
void do_something(Container&& container) {
return y(std::forward<Container>(container);
}
但是当容器同时具有成员函数y和全局非成员函数时,y也适用于它。存在编译错误,因为对于函数的第二个版本,模板参数生成错误,因为需要成员函数y。
我知道如何解决这个问题吗?
注意:这与仅检测某个类是否具有给定签名的功能不同。对不起,如果问题似乎要求!下面接受的答案应该让我的意图更清楚。
答案 0 :(得分:3)
典型的方法是调度到一对函数,其中如果满足条件则优先选择一个函数,而另一个函数只是后备函数。好消息是你甚至不需要enable_if
,只需要跟踪decltype
:
template <class C>
auto do_something_impl(C&& c, int)
-> decltype(std::forward<C>(c).y())
{
return std::forward<C>(c).y();
}
template <class C>
auto do_something_impl(C&& c, ...)
-> decltype(y(std::forward<C>(c))
{
return y(std::forward<C>(c));
}
现在只需传入0
:
template <class C>
auto do_something(C&& c)
-> decltype(do_something_impl(std::forward<C>(c), 0))
{
return do_something_impl(std::forward<C>(c), 0);
}
int
的转换序列优于...
的转换序列,因此如果类型具有您想要的成员函数,则即使两者都是可行的候选者,也会优先选择该重载。