c++ - 我该如何正确处理这个 SFINAE?

标签 c++ c++11 sfinae

我在根据参数包的特征启用/禁用重载时遇到了问题。这是我试图回答的另一个问题。我有一个静态的 go() 函数,如果所有的 Mixins 类型都有一个静态的 check() 方法,它应该被调用。同样,如果 Mixins没有 有一个 check( ) 方法。我尝试创建基于此策略启用的重载,但出于某种原因,当我调用它时,它选择了尝试调用 handle()second 重载:

template<class T, class...>
using first = T;

template<class... Mixins>
struct Checker
{
public:
    template<class =
             first<void,
                   typename std::enable_if<has_check<Mixins>::value>::type...>>
    static void go()
    {
        auto x{ (Mixins::check(), 0)... };
        (void)x;
    }

    static void go()
    {
        auto x{ (Mixins::handle(), 0)... };
        (void)x;
    }
};

struct A { static void check() { std::cout << "check() "; } };
struct B { static void check() { std::cout << "check() "; } };

int main()
{
    Checker<A, B>::go();
}

Here is a demo.

我收到一条错误消息,提示 A 没有名为 handle() 的成员。这一直困扰着我,但我找不到解决方法。如何解决此问题?如何根据参数包正确协调重载决议?

最佳答案

你没有什么可以区分go的两种味道的.重载解析将优先选择非模板 go当两者都可行时。 The ... vs. int technique works :

template<class... Mixins>
struct Checker
{
private:
    template<class =
             first<void,
                   typename std::enable_if<has_check<Mixins>::value>::type...>>
    static void foo(int)
    {
        auto x{ (Mixins::check(), 0)... };
        (void)x;
    }

    static void foo(...)
    {
        auto x{ (Mixins::handle(), 0)... };
        (void)x;
    }

public:
    static void go() {
        foo(0);
    }
};

由于 foo 的两个重载可以调用foo(0) ,但是foo(int)是比 foo(...) 更好的匹配这样当它没有被 SFINAE 淘汰时,重载解析会更喜欢它。

编辑:我在这里犯了一个错误,我假设

template<class =
         first<void,
               typename std::enable_if<has_check<Mixins>::value>::type...>>

SFINAE 会正确地消除 foo 的过载吗? .但是,这里的错误不是替换失败,因为未命名函数模板参数的默认值不依赖于函数模板的参数。通常,当你有一个类型参数化的类时 T并且您想约束成员函数 f基于 T 的一些属性,您使用 T 的别名强制该依赖项:

template <class T>
struct foo {
  template <class U=T,
            class=typename std::enable_if<std::is_integral<U>::value>::type>
  void f();
};

但是,同样的技巧在 OP 的情况下不起作用,因为 OP 的类是在包上参数化的,并且无法为参数包提供默认值。我们必须更狡猾:

template<class T = void,
         class = first<T, typename std::enable_if<has_check<Mixins>::value, T>::type...>>
static void foo(int)
{
    auto x{ (Mixins::check(), 0)... };
    (void)x;
}

同时强制 first<...>enable_if<...>扩展对 SFINAE 有效。 See it at Coliru.

关于c++ - 我该如何正确处理这个 SFINAE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21948049/

相关文章:

c++ - Structure 内的指针变量,具有相同的结构类型

c++ - strcpy_s 不适用于 gcc

c++ - 为什么我们必须在箭头符号( -> )之后再次指定数据类型

c++ - 是否可以通过桶迭代器从 std::unordered_set 中删除元素?

c++ - SFINAE + decltype 的 g++ 4.7 错误?

c++ - 我可以在控制流语句中使用 SFINAE 测试吗?

c++ - Visual Studio 2010 的模板问题

c++ - 如何在 Vista/Server 2008 上使用 std::shared_mutex?

c++ - 在opencv中发现凸性缺陷? [崩溃取决于给定的输入图像..]

c++ - 为一些具有模板参数限制的外部模板类定义部分特化