我可以禁用SFINAE吗?

qua*_*ant 9 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;
}
Run Code Online (Sandbox Code Playgroud)

实例

auto出于各种原因我可能需要说明符,但上述程序会产生以下错误:

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

虽然如此,但它并没有特别有用.在这个例子中很明显我忘了提供一个C::type,但你可以看到,在较大的程序中,这可能会变得非常混乱.

失败的真正原因是在编译器错误消息中埋藏了几行:

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

在一个实际的代码库此消息可以是下几百或几千(或数百千)错误消息(和上述同样大的组消息可能已经从另一变化出现)线.考虑到在真实情况下我们可能甚至不知道要寻找什么,这可能会非常混乱.

一个错误告诉我,A因为C::type没有声明失败的声明会更有帮助.

当然有很多情况下SFINAE是有用且必要的,所以我不想以某种方式完全关闭这种语言功能.但是我可以禁用此特定功能的SFINAE规则吗?

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

n. *_* m. 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'");
  }
};
Run Code Online (Sandbox Code Playgroud)

get_type(永远不会失败)和has_type(使用 SFINAE)是到处都有描述的标准练习。