我可以禁用SFINAE吗?

Can I disable SFINAE?

本文关键字:SFINAE 我可以      更新时间:2023-10-16

假设我有这样一个程序

struct A
{
  template <typename T>
  static auto fun() -> typename T::type { }
};
struct C
{
    // doh! I forgot to add a typedef for type!
};
int main() {
    A::fun<C>();
    return 0;
}

生活例子我可能出于各种原因需要auto说明符,但是上面的程序产生以下错误:

prog.cpp:13:12: error: no matching function for call to ‘A::fun()’
  A::fun<C>();

虽然这是真的,但并不是特别有用。很明显,在这个例子中,我忘记提供C::type,但是您可以看到,在较大的程序中,这可能会变得非常令人困惑。

真正的失败原因隐藏在编译器错误消息的几行后面:

prog.cpp:7:15:错误:' struct C '中没有名为' type '的类型

在实际的代码库中,此消息可能位于数百或数千行(或数百数千行)错误消息之下(并且位于可能由另一个更改产生的同样大的消息集之上)。考虑到在一个真实的场景中,我们可能甚至不知道要寻找什么,这可能会非常令人困惑。

一个简单的错误告诉我A的声明失败,因为C::type没有声明,这将更有帮助。

当然在很多情况下SFINAE是有用和必要的,所以我不想以某种方式完全关闭这个语言特性。但是我可以禁用这个特定函数的SFINAE规则吗?

换句话说,我可以在函数声明中添加一些东西来强制编译器尝试编译该函数,并在替换失败时产生错误吗?

没有办法禁用SFINAE。c++没有可以随意启用和禁用的特性。有一种方法可以使SF部分永远不会发生,从而在其他地方触发E。

struct A
{
  template <typename T>
  static auto fun() -> typename get_type<T>::type { 
    static_assert(has_type<T>::value, "Template parameter has no type member named 'type'");
  }
};

get_type(从不失败)和has_type(使用SFINAE)是无处不在的标准练习。