Mari kita lihat contoh sederhana penggunaan enable_if

template <bool, typename T = void>
struct enable_if
{
};

template <typename T>
struct enable_if<true, T>
{
    typedef T type;
};
  1. Di sini diharapkan y akan menjadi int, karena T adalah tipe "diaktifkan" kami.
template <typename T, typename Y = typename std::enable_if<std::is_integral<T>::value, T>::type>
void do_stuff(T t)
{
    (void)t;
    Y y;
    std::cout << typeid(y).name() << std::endl;
}
do_stuff(15); // int
  1. Tapi di sini semuanya berjalan agak tidak eksplisit bagi saya, dan y akan disimpulkan menjadi apa pun jenis argumen yang sebenarnya.
template <typename T, typename Y = typename std::enable_if<std::is_integral<T>::value, T>::type>
void do_stuff(T t, Y y)
{
    (void)t;
    std::cout << "do_stuff integral\n";
    std::cout << typeid(y).name() << std::endl;
}

do_stuff(15, 14.3);  // double

Jadi pertanyaan saya adalah:

Apa aturan yang memaksa kompiler untuk memprioritaskan pengurangan y dari argumen aktual yang diteruskan dan mengabaikan type yang diaktifkan dari enable_if ?

1
ampawd 27 Mei 2021, 04:18

1 menjawab

Jawaban Terbaik

Argumen template default hanya digunakan ketika argumen template tidak ditentukan secara eksplisit dan parameter template tidak dapat disimpulkan. Untuk kasus ini, Y dapat disimpulkan dari 14.3 sebagai double, maka argumen default tidak akan digunakan. Demikian pula, dalam contoh pertama Anda juga dapat mengabaikan pemeriksaan std::enable_if dengan menentukan argumen template.

do_stuff<int, double>(15); // double

BTW Anda dapat menambahkan parameter templat non-tipe menggunakan std::enable_if dalam deklarasi tipe untuk membuat pemeriksaan berlaku setiap saat.

template <typename T, typename Y, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
void do_stuff(T t, Y y)
2
songyuanyao 27 Mei 2021, 01:42