繁体   English   中英

enable_if、SFINAE 和模板参数?

[英]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替换了像intF这样的简单类型。 我们不关心传递给它的实际参数,所以这就是它未命名的原因。

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_tis_integral_v是缩写所有::valuetypename...::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM