首页 > 解决方案 > 当多个重载超过 SFINAE 时创建首选重载

问题描述

struct A { void a() { puts("a"); } };
struct B { void b() { puts("b"); } };
struct C : A, B {};

template <typename T> decltype(&T::a, (void)0) SFINAE(T t) { t.a(); }
template <typename T> decltype(&T::b, (void)0) SFINAE(T t) { t.b(); }

int foo()
{
    SFINAE(A{}); // works fine, calls a
    SFINAE(B{}); // works fine, calls b
    SFINAE(C{}); // compile error
}

上面的代码在使用具有aand的类型调用 SFINAE 时失败b,因此使两个模板都有效,从而导致模棱两可的调用。如何修复上述代码以在模棱两可的情况下更喜欢第一个重载?所以SFINAE(C{})应该调用a

标签: c++templatesc++14

解决方案


您可以通过引入转换来消除呼叫歧义:

template <typename T> decltype(&T::a, (void)0) impl(T t, int) { t.a(); }
template <typename T> decltype(&T::b, (void)0) impl(T t, unsigned) { t.b(); }

template <typename T> void SFINAE(T && t) { impl(std::forward<T>(t), 42); }

传递42type int,编译器将选择第一个重载作为更好的匹配。

Demo


推荐阅读