c++ - 具有函数和模拟部分模板特化的 SFINAE

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

我正在尝试创建一个函数 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。

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

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

最佳答案

典型的方法是分派(dispatch)到一对函数,如果满足您的条件,其中一个是首选,另一个只是后备。好处是你甚至不需要 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 的转换序列比到 ... 的转换序列要好,所以如果类型有你想要的成员函数,那么重载将是首选,即使两者都是可行的候选人。

关于c++ - 具有函数和模拟部分模板特化的 SFINAE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40196724/

相关文章:

c++ - 在对话框窗口上使用图标 C++ Win32 API

c++ - 对范围循环感到困惑

c++ - 我的应用程序在 KNearest::find_nearest 处崩溃

C++11 - std::function、模板和函数对象、奇怪的问题

C++ 在键上将两个映射相交,保留第一个映射的值

C# 到 C++11 的转换 : delegate templates

c++ - 将 std::async 与模板函数一起使用

C++ 自定义分配器大小参数作为模板参数会引发编译器错误

c++ - 是否可以为 std::any-like 容器转发具有匹配模板类型的函数调用?

c++ - 程序在 VS2017 上以 "abort() has been called"错误结束