我可以禁用SFINAE吗?

时间:2014-08-26 02:36:55

标签: c++

假设我有这个程序

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;
}

Live example

出于各种原因,我可能需要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规则吗?

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

1 个答案:

答案 0 :(得分:4)

无法禁用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)是到处描述的标准练习。