假设我有这个程序
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规则吗?
换句话说,我可以在函数声明中添加一些内容来强制编译器尝试编译函数,并在发生替换失败时产生错误吗?
答案 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)是到处描述的标准练习。