【问题标题】:SFINAE with functions and emulating partial template specialization具有功能和模拟部分模板专业化的 SFINAE
【发布时间】:2016-10-22 20:27:16
【问题描述】:

我正在尝试制作一个函数 X,该函数在提供成员函数 Y 时专门化,如果未提供成员函数 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。

知道如何解决这个问题吗?

注意:这与仅检测类是否具有给定签名的功能不同。对不起,如果问题似乎在问这个问题!下面接受的答案应该让我的意图更清楚。

【问题讨论】:

  • @bolov 我编辑了我的问题并添加了一条注释。下面巴里的回答澄清了我想问的问题!

标签: c++ c++11 templates template-specialization sfinae


【解决方案1】:

典型的方法是分派到一对函数,如果满足您的条件,则首选其中一个函数,而另一个只是后备。好消息是你甚至不需要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 的转换顺序比到... 的转换顺序要好,因此如果该类型具有您想要的成员函数,那么即使两者都是可行的候选者,重载也是首选。

【讨论】:

  • 这很漂亮。我从来没有想过这个。我觉得尾随返回类型会很有用,但我没有在等式中包含省略号。我走上了短视的道路。
  • 只是出于好奇,您是如何偶然发现这种技术的?
  • 啊,刚刚想到了一个替代方案。继承层次结构也可以用来模仿这里带有省略号的“首选”调度:)
  • @Curious 是的,如果您需要两个以上的选择,还有其他事情可以做。三个你可以做intlong...,但那时我宁愿有choice&lt;0&gt;choice&lt;1&gt;,...
  • @Barry 什么,你不喜欢'\0'charintlonguser_defined_type_convertible_from_char...?异端! :P
猜你喜欢
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
  • 2020-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多