[英]enable_if, SFINAE and template parameters?
我试图了解enable_if
和 SFINAE。 至此,我对模板的使用已经明确将模板arguments传递给模板参数或在实例化时扣除模板参数。 我对下面的代码感到困惑 enable_if<>::type (typedef int type) 的成员如何成为模板参数。 即参数列表变为<class T = int, int* = nullptr>
。 我希望这样的参数是int Z = nullptr
。
有谁知道我在理解为什么enable_if
分配的这些模板参数起作用时缺少什么?
谢谢
#include <type_traits>
#include <iostream>
#if 1
template <class T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
void do_stuff(T& t) {
std::cout << "do_stuff integral\n";
}
#endif
#if 0 // understood
template <class T>
typename std::enable_if<std::is_integral<T>::value,
void>::type
do_stuff(T& t) {
std::cout << "do_stuff integral\n";
}
#endif
struct S {};
int main(int argc, char *argv[])
{
int i = 1;
do_stuff(i);
//do_stuff<S>(S{});
return 0;
}
有两种模板参数:
模板参数的名称是可选的
模板参数可以有默认值
template <class T>
struct X {};
用法:
X<int> x{};
template <class T = int>
struct X {};
用法:
X<> x1{};
X<char> x2{};
template <class>
struct X {};
用法:
X<int> x{};
template <class = int>
struct X {};
用法:
X<> x1{};
X<char> x2{};
template <int I>
struct X {};
用法:
X<24> x{};
template <int I = 24>
struct X {};
用法:
X<> x1{};
X<11> x2{};
template <int>
struct X {};
用法:
X<11> x{};
template <int = 24>
struct X {};
用法:
X<> x1{};
X<11> x2{};
对于 SFINAE,该技术需要一个默认值。 由于您不关心 class 中的参数,因此您可以跳过其名称。 至于类型或非类型,您可以选择在您的特定情况下哪个更容易编写。
该参数是匿名的。 指定了类型和默认值,但以后没有实际引用它。
template<typename> struct A; // fine
template<int> struct B; // fine
template<typename F, F = nullptr> struct C; // fine
using AI = A<int>;
using BI = B<5>;
using CI = C<int, 5>;
using CD = C<void*>; // all fine
using Oops = C<char>; // not fine
您的案例只是用大喇叭typename std::enable_if<...>::type
替换了像int
和F
这样的简单类型。 我们不关心传递给它的实际参数,所以这就是它未命名的原因。
template <class T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
void do_stuff(T &t) {
std::cout << "do_stuff integral\n";
}
插入T = int
, typename std::enable_if<std::is_integral<T>::value>::type = void
,所以第二个默认参数看起来像void* = nullptr
,这意味着它是一个未命名的类型参数void*
默认为nullptr
。 请注意,类型名typename
类型模板参数类型的一部分。 它没有作为类型模板参数的引入者的其他功能。 另外,请注意现代 C++ 的写法是
// typename instead of class is more a style thing
template<typename T, std::enable_if_t<std::is_integral_v<T>>* = nullptr>
其中enable_if_t
和is_integral_v
是缩写所有::value
和typename...::type
废话的别名:
namespace std {
template<typename T>
constexpr inline bool is_integral_v = std::is_integral<T>::value;
template<bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.