对于 class 模板,std::enable_if 相对于 static_assert 的优势是什么?
What is the advantage of std::enable_if over static_assert for class templates?
我想知道 std::enable_if
over static_asserts
to prevent template instantiation. This answer suggests, that std::enable_if
allows SFINAE, which is a convincing argument in the case of function templates 的优势。
然而,这个论点对 class templates (and variable templates) 来说是否合理?据我所知,那里没有涉及重载决议,这使得 SFINAE - 再次,据我所知 - 不相关,但我可能是错的。如果是这样,你能举个例子吗?
如果不是,我假设 static_assert
是针对 class 模板的给定问题(防止模板实例化)的更好解决方案,因为它可以说更明确、简洁和可读允许自定义错误消息。这是正确的还是我遗漏了 SFINAE 以外的一点?
However is this argument legitimate for class templates (and variable templates)? As far as I know, there is no overload resolution involved there, making SFINAE - again, as far as I know - not relevant, but I might be wrong. If so, can you name an example?
您可以专业化 class 模板,SFINAE 可用于在专业化之间进行选择。它还将阻止此类实例化(到那时,可能 ill-formed)class/它的特化,而不是由于 static_assert
.
而无法编译
处理几个不同的类型可以像你说的那样通过专门化来完成:
template <class>
class foo;
template <>
class foo <int> { /* int implementation */ };
template <>
class foo <char> { /* char implementation */ };
现在考虑我们想要特化多个类型,并且我们希望 float
和 double
处于相同的特化中。如果没有 SFINAE,我们无法做到这一点,因此为了避免重复实现,我们使用继承:
class foo_fp_implementation {
/* specialise for all floating point */
};
template <>
class foo <float> : foo_fp_implementation {};
template <>
class foo <double> : foo_fp_implementation {};
到目前为止,我们已经避免了 SFINAE,但是如果您想要一个接受具有特定接口的所有类型的专业化怎么办?示例:有方法 int bar ()
?我们可以尝试使用上面的技巧并列出所有可能的类型,但是如果要维护的类型太多,或者您希望其他可能使用自己的类型的人可以使用它怎么办。这里 SFINAE 来拯救:
template <class, class = int>
class foo;
template <class T>
class foo <T, decltype(T().bar())> {
// implement using bar interface
};
// other specialisations...
遇到上述情况,static_assert
根本无能为力
总而言之,SFINAE 有助于根据精确的 行为 而不是精确的 类型 .
进行专业化
std::enabled_if 在 SFIANE 中用于模板 类、方法和 ....
static_assert 用于在编译时检查合约,并提供有用的错误消息。
我想知道 std::enable_if
over static_asserts
to prevent template instantiation. This answer suggests, that std::enable_if
allows SFINAE, which is a convincing argument in the case of function templates 的优势。
然而,这个论点对 class templates (and variable templates) 来说是否合理?据我所知,那里没有涉及重载决议,这使得 SFINAE - 再次,据我所知 - 不相关,但我可能是错的。如果是这样,你能举个例子吗?
如果不是,我假设 static_assert
是针对 class 模板的给定问题(防止模板实例化)的更好解决方案,因为它可以说更明确、简洁和可读允许自定义错误消息。这是正确的还是我遗漏了 SFINAE 以外的一点?
However is this argument legitimate for class templates (and variable templates)? As far as I know, there is no overload resolution involved there, making SFINAE - again, as far as I know - not relevant, but I might be wrong. If so, can you name an example?
您可以专业化 class 模板,SFINAE 可用于在专业化之间进行选择。它还将阻止此类实例化(到那时,可能 ill-formed)class/它的特化,而不是由于 static_assert
.
处理几个不同的类型可以像你说的那样通过专门化来完成:
template <class>
class foo;
template <>
class foo <int> { /* int implementation */ };
template <>
class foo <char> { /* char implementation */ };
现在考虑我们想要特化多个类型,并且我们希望 float
和 double
处于相同的特化中。如果没有 SFINAE,我们无法做到这一点,因此为了避免重复实现,我们使用继承:
class foo_fp_implementation {
/* specialise for all floating point */
};
template <>
class foo <float> : foo_fp_implementation {};
template <>
class foo <double> : foo_fp_implementation {};
到目前为止,我们已经避免了 SFINAE,但是如果您想要一个接受具有特定接口的所有类型的专业化怎么办?示例:有方法 int bar ()
?我们可以尝试使用上面的技巧并列出所有可能的类型,但是如果要维护的类型太多,或者您希望其他可能使用自己的类型的人可以使用它怎么办。这里 SFINAE 来拯救:
template <class, class = int>
class foo;
template <class T>
class foo <T, decltype(T().bar())> {
// implement using bar interface
};
// other specialisations...
遇到上述情况,static_assert
根本无能为力
总而言之,SFINAE 有助于根据精确的 行为 而不是精确的 类型 .
进行专业化std::enabled_if 在 SFIANE 中用于模板 类、方法和 .... static_assert 用于在编译时检查合约,并提供有用的错误消息。