类模板中的成员函数 SFINAE:详细说明
在 C 世界中,SFINAE(替换失败不是错误)使通过防止编译期间的实例化错误来优化模板。然而,在处理类模板的成员函数时,SFINAE 的行为可能会出现意外。
成员函数 SFINAE 的问题
考虑以下代码:
<code class="cpp">template <typename T> struct Foo { typename std::enable_if<std::is_same<T, A>::value>::type bar(); typename std::enable_if<std::is_same<T, B>::value>::type bar(); };</code>
与预期相反,此代码会导致错误消息。 SFINAE 没有按预期用于类模板中的成员函数。
SFINAE 和推导模板参数
问题的关键在于 SFINAE 对推导模板参数的依赖。仅当从函数调用推导模板参数时它才有效。对于成员函数,不会推导模板参数,而是显式提供。
使用推导参数的解决方案
为了解决这个问题,我们可以修改代码如下:
<code class="cpp">template<typename T> struct Foo { template<typename U = T> typename std::enable_if<std::is_same<U,A>::value>::type bar() { } template<typename U = T> typename std::enable_if<std::is_same<U,B>::value>::type bar() { } };</code>
现在,当调用 Foo()(x) 时,编译器会推导出模板参数 T 并根据 x 选择正确的重载。这种方法允许 SFINAE 按预期运行。
或者:显式类模板专业化
如果类的结构至关重要且无法修改,则替代解决方案包括显式类模板特化:
<code class="cpp">template <typename> struct Foo; template <> struct Foo<A> { void bar() {} }; template <> struct Foo<B> { void bar() {} };</code>
这里,编译器根据提供的类型确切地知道要实例化哪个特化。它不依赖 SFINAE 进行专业选择。
以上是为什么 SFINAE 在类模板中使用成员函数时会失败?的详细内容。更多信息请关注PHP中文网其他相关文章!