c++ - الوسيطة الافتراضية للقالب تفقد نوع المرجع الخاص بها




templates template-deduction (2)

بالنسبة foo<int>(a) ، يتم استخلاص ARG_T من a ، ولا يتم أخذها من وسيطة القالب الافتراضية. نظرًا لأنها معلمة دالة حسب القيمة ، وهي تعبير عن النوع int ، يتم استنتاجها كـ int .

بشكل عام ، لا يتم استخدام وسيطات القالب الافتراضية عندما يمكن لخصم وسيطة القالب اكتشاف ماهية الوسيطة.

ولكن يمكننا فرض استخدام الوسيطة الافتراضية من خلال تقديم سياق غير مستخلص للمعلمة الدالة. على سبيل المثال:

template <class T, class ARG_T = T&>
T foo(std::enable_if_t<true, ARG_T> v1){
    //...
}

أو الأداة المساعدة type_identity C ++ 20 ، مثل الإجابة الأخرى يوضح.

يعتبر

#include <iostream>
#include <type_traits>

template <class T, class ARG_T = T&>
T foo(ARG_T v){
    return std::is_reference<decltype(v)>::value;
}

int main() {
    int a = 1;
    std::cout << foo<int>(a) << '\n';
    std::cout << foo<int, int&>(a) << '\n';
}

أتوقع أن يكون الناتج 1 في كلتا الحالتين. ولكن في الحالة class ARG_T = T 0: بما يتماشى مع الحالة الافتراضية class ARG_T = T بدلاً من class ARG_T = T& .

ماذا ينقصني؟


تحتاج إلى إيقاف خصم وسيطة القالب لـ ARG_T من وسيطة الدالة v ، (بمساعدة std::type_identity ، والتي يمكن استخدامها لاستبعاد وسيطات محددة من الخصم) ؛ خلاف ذلك ، لن يتم استخدام وسيطة القالب الافتراضية. على سبيل المثال

template <class T, class ARG_T = T&>
T foo(std::type_identity_t<ARG_T> v){
    return std::is_reference<decltype(v)>::value;
}

LIVE

راجع للشغل: إذا كان برنامج التحويل البرمجي لا يدعم std::type_identity (منذ std::type_identity C ++ 20) ، فيمكنك إنشاء ملفك الشخصي.

template<typename T> struct type_identity { typedef T type; };
template< class T >
using type_identity_t = typename type_identity<T>::type;




argument-deduction