Shabloni foydalanish <typename>

Kodni quyidagicha ayting:

#include 

template
void printnum(int i) {

    std::cout<<"in int method:"<<< i<
void printnum(char i) {

    std::cout<<"in char method:"<<<(int)i<(2);
    printnum(3);
}

chiqdi:

in int method:
2
in int method:
3

My intention for this test code was to confirm/not-confirm my (natural) understanding of the use of a template template. As there is no parameter for the template type given, I'd thought that such a construct would help in overload resolution. That is, without the template annotations it is clear that I would get the above output. But with the template annotation I'd have thought that I maybe could force the compiler to take (in case of the 3-call) the char-variant of the printnum() function, which isn't the case.

So my general question is: What is the use of the template construct?

2
Albatta, "foydalanish" bor. C ++ kutubxonasida parametr sifatida bitta sinfni oladigan ko'plab shablonlar mavjud.
qo'shib qo'ydi muallif Sam Varshavchik, manba
Foydalanish bitta shablon parametri bilan shabloni aniqlash: sinf. Mana shuning o'zi. " int " va "2" kabi ikkala kod ham int parametrini tanlaydi. Andoza parametri bir omil emas.
qo'shib qo'ydi muallif Sam Varshavchik, manba
Bu kodda hech qanday nuqta yo'q . Shabl argumenti hamma joyda (ortiqcha yuk hal etish uchun juda ham kam) ishlatilmagani uchun bu muhim emas. Bunga printnum (3) ni kiritishingiz mumkin va int parametrini haddan tashqari yuklash hali printnum (int) va printnum (char) ni tanlang.
qo'shib qo'ydi muallif WhozCraig, manba
Bu kodda hech qanday nuqta yo'q . Shabl argumenti hamma joyda (ortiqcha yuk hal etish uchun juda ham kam) ishlatilmagani uchun bu muhim emas. Bunga printnum (3) ni kiritishingiz mumkin va int parametrini haddan tashqari yuklash hali printnum (int) va printnum (char) ni tanlang.
qo'shib qo'ydi muallif WhozCraig, manba
@WhozCraig: Ha, bu juda aniq, chunki kod men buni "umid qilgan" narsani qilmagan va standart haddan tashqari yukni o'lchash xatti-harakatlarini amalga oshirgan, "bo'sh shablonni" ishlatish foydasiz edi. Ehtimol, bunday "bo'sh shablonni" mantiqiy qaerda misol keltira olasiz?
qo'shib qo'ydi muallif FloriHe, manba
@WhozCraig: Ha, bu juda aniq, chunki kod men buni "umid qilgan" narsani qilmagan va standart haddan tashqari yukni o'lchash xatti-harakatlarini amalga oshirgan, "bo'sh shablonni" ishlatish foydasiz edi. Ehtimol, bunday "bo'sh shablonni" mantiqiy qaerda misol keltira olasiz?
qo'shib qo'ydi muallif FloriHe, manba
Ha, lekin bu savolga javob bermaydi
qo'shib qo'ydi muallif FloriHe, manba
Ha, lekin bu savolga javob bermaydi
qo'shib qo'ydi muallif FloriHe, manba

8 javoblar

Buning asosiy sababi, argumentning aniq ixtisoslashuviga imkon berishdir. Tasavvur qiling:

#include 

template void printnum(int i);

template<>
void printnum(int i) {
    std::cout<<"in int method: "<<>
void printnum(int i) {
    std::cout<<"in char method: "<(2);
    printnum(3);
}

Ushbu dastur yozadi:

in int method: 2
in char method: 3

It creates two different printnum(int) functions that are selected by the explicit template parameter. The main use of this is when you want to call printnum(int) from some other template function that has a T type parameter.

1
qo'shib qo'ydi
Rahmat, bu men izlayotgan narsa edi, bu mantiqqa to'g'ri keladi.
qo'shib qo'ydi muallif FloriHe, manba

Buning asosiy sababi, argumentning aniq ixtisoslashuviga imkon berishdir. Tasavvur qiling:

#include 

template void printnum(int i);

template<>
void printnum(int i) {
    std::cout<<"in int method: "<<>
void printnum(int i) {
    std::cout<<"in char method: "<(2);
    printnum(3);
}

Ushbu dastur yozadi:

in int method: 2
in char method: 3

It creates two different printnum(int) functions that are selected by the explicit template parameter. The main use of this is when you want to call printnum(int) from some other template function that has a T type parameter.

1
qo'shib qo'ydi
Rahmat, bu men izlayotgan narsa edi, bu mantiqqa to'g'ri keladi.
qo'shib qo'ydi muallif FloriHe, manba

Buning sababi, chaqirilayotgan funktsiya argumentning turi bilan belgilanadi. 2 va 3 ham int turidagi (literal qiymatlar), shuning uchun birinchi "variant" (yaxshiroq ta'rif ) deyiladi.

Agar qilgan bo'lsangiz

printnum('A');
printnum('B');

Sizning funktsiyangizning ikkinchi shakli ikkala holatda ham chaqiriladi.

Har qanday holatda siz shablonlarni noto'g'ri ishlatasiz. Til xususiyatini suiiste'mol qilish bu xususiyatning qiymatini tekshirish uchun kambag'allikdir.

Keyinchalik to'g'ri ishlatish xuddi shunday bo'lishi mumkin;

template
void printnum(T i)
{
     std::cout<< i << std::endl;
}

bu degani

printnum(1);
printnum("ABC");

1 raqamini keyin alohida satrlarda ABC mag'lubiyatga yozib chiqadi.

int versiyasi uchun boshqa narsa qilishni xohlasangiz, oldingi shablonni ta'rifidan keyin -

template<> printnum(int x)
{
    std::cout<<"in int method:"<<< i<

printnum (1) (yoki printnum() int turidagi boshqa qiymatlar berilgan) uchun chaqiriladi. Xuddi shunday, agar siz boshqa turlarga ixtisoslashmoqchi bo'lsangiz.

1
qo'shib qo'ydi
Har qanday holatda, "kod
qo'shib qo'ydi muallif Peter, manba
Buning sababi, siz o'zingiz foydalangan kod bilan nima yomonligini tushuntirishga majbur qildingiz. Va kambag'al kod bilan muammoni cheklab qo'yganingizdek, siz bergan koddan kutilgan narsalarni qanday qilib bajarishni namoyish qilgandim.
qo'shib qo'ydi muallif Peter, manba
Men shunday deb o'ylamayman. Bo'sh shablon konstruktsiyasidan foydalanishni tushunmayapman, chunki faqat foydali bo'lmagan kod bilan namuna yaratishim mumkin. Va bu kodni qanday qilib to'g'ridan-to'g'ri hal qilish kerakligi haqida maslahat berish orqali umumiy savolga javob berish kerak, lekin bu savolga nisbatan qiymatga ega emas
qo'shib qo'ydi muallif FloriHe, manba
Ha, buni to'liq tushunaman. Misol yaxshi kod ko'rsatish uchun tanlanmagan. Savolga quyidagicha javob berildi: shablonni ishlatish nima? ?
qo'shib qo'ydi muallif FloriHe, manba

Buning sababi, chaqirilayotgan funktsiya argumentning turi bilan belgilanadi. 2 va 3 ham int turidagi (literal qiymatlar), shuning uchun birinchi "variant" (yaxshiroq ta'rif ) deyiladi.

Agar qilgan bo'lsangiz

printnum('A');
printnum('B');

Sizning funktsiyangizning ikkinchi shakli ikkala holatda ham chaqiriladi.

Har qanday holatda siz shablonlarni noto'g'ri ishlatasiz. Til xususiyatini suiiste'mol qilish bu xususiyatning qiymatini tekshirish uchun kambag'allikdir.

Keyinchalik to'g'ri ishlatish xuddi shunday bo'lishi mumkin;

template
void printnum(T i)
{
     std::cout<< i << std::endl;
}

bu degani

printnum(1);
printnum("ABC");

1 raqamini keyin alohida satrlarda ABC mag'lubiyatga yozib chiqadi.

int versiyasi uchun boshqa narsa qilishni xohlasangiz, oldingi shablonni ta'rifidan keyin -

template<> printnum(int x)
{
    std::cout<<"in int method:"<<< i<

printnum (1) (yoki printnum() int turidagi boshqa qiymatlar berilgan) uchun chaqiriladi. Xuddi shunday, agar siz boshqa turlarga ixtisoslashmoqchi bo'lsangiz.

1
qo'shib qo'ydi
Har qanday holatda, "kod
qo'shib qo'ydi muallif Peter, manba
Buning sababi, siz o'zingiz foydalangan kod bilan nima yomonligini tushuntirishga majbur qildingiz. Va kambag'al kod bilan muammoni cheklab qo'yganingizdek, siz bergan koddan kutilgan narsalarni qanday qilib bajarishni namoyish qilgandim.
qo'shib qo'ydi muallif Peter, manba
Men shunday deb o'ylamayman. Bo'sh shablon konstruktsiyasidan foydalanishni tushunmayapman, chunki faqat foydali bo'lmagan kod bilan namuna yaratishim mumkin. Va bu kodni qanday qilib to'g'ridan-to'g'ri hal qilish kerakligi haqida maslahat berish orqali umumiy savolga javob berish kerak, lekin bu savolga nisbatan qiymatga ega emas
qo'shib qo'ydi muallif FloriHe, manba
Ha, buni to'liq tushunaman. Misol yaxshi kod ko'rsatish uchun tanlanmagan. Savolga quyidagicha javob berildi: shablonni ishlatish nima? ?
qo'shib qo'ydi muallif FloriHe, manba

T barcha turdagi funktsiyalar uchun sizning oilangiz bor ( T va int ); va tasodifan, hammasi xuddi shu narsani qilmoqda. T barcha turlari uchun char parametri sifatida boshqa funktsiya oilangiz mavjud.

Omitting the name T doesn't convey any magical properties on your function templates: template void f(); and template void f(); are exactly equivalent.

printnum(2) instantiates one function from the first family (for T == int), and one function from the second family, and performs overload resolution on them. The function from the first family wins. Same with printnum(3)


Siz shablonni ixtisoslashtirilgan deb o'ylashingiz mumkin:

template  void printnum(T);

template<>
void printnum(int i) {

    std::cout<<"in int method:"<<< i<
void printnum(char i) {

    std::cout<<"in char method:"<<<(int)i<

Namoyish

Bu yerda yagona funktsiya oilasi mavjud. Bu oilaning faqat ikkita a'zosi aniqlangan (har qanday boshqa misolni ishlatish uchun urinish bog'lanuvchi xatolikka olib keladi). Andoza argumenti aniq bir oila a'zosini aniq tanlaydi; chunki qo'ng'iroq qilish uchun faqatgina bitta mavjud funktsiya mavjud, ortiqcha yuk qabul qilinmaydi.

1
qo'shib qo'ydi
Odatda bunday emas. Funktsiya shablonini nima uchun yaratmoqchisiz va shablon parametrlarini ishlatmasligingiz noto'g'ri.
qo'shib qo'ydi muallif Igor Tandetnik, manba
Rahmat, bu yaxshi tushuntirish. Shunday qilib, umuman olganda, oilaning barcha boshqa funktsiyalari bilan bir xil bo'lgan kompilyatsiya vaqtida tanlangan funktsiyalari oilasini yaratish umuman yagona ta'sir. Lekin nima uchun bu mantiqan ekanligini tushunmayapman.
qo'shib qo'ydi muallif FloriHe, manba

T barcha turdagi funktsiyalar uchun sizning oilangiz bor ( T va int ); va tasodifan, hammasi xuddi shu narsani qilmoqda. T barcha turlari uchun char parametri sifatida boshqa funktsiya oilangiz mavjud.

Omitting the name T doesn't convey any magical properties on your function templates: template void f(); and template void f(); are exactly equivalent.

printnum(2) instantiates one function from the first family (for T == int), and one function from the second family, and performs overload resolution on them. The function from the first family wins. Same with printnum(3)


Siz shablonni ixtisoslashtirilgan deb o'ylashingiz mumkin:

template  void printnum(T);

template<>
void printnum(int i) {

    std::cout<<"in int method:"<<< i<
void printnum(char i) {

    std::cout<<"in char method:"<<<(int)i<

Namoyish

Bu yerda yagona funktsiya oilasi mavjud. Bu oilaning faqat ikkita a'zosi aniqlangan (har qanday boshqa misolni ishlatish uchun urinish bog'lanuvchi xatolikka olib keladi). Andoza argumenti aniq bir oila a'zosini aniq tanlaydi; chunki qo'ng'iroq qilish uchun faqatgina bitta mavjud funktsiya mavjud, ortiqcha yuk qabul qilinmaydi.

1
qo'shib qo'ydi
Odatda bunday emas. Funktsiya shablonini nima uchun yaratmoqchisiz va shablon parametrlarini ishlatmasligingiz noto'g'ri.
qo'shib qo'ydi muallif Igor Tandetnik, manba
Rahmat, bu yaxshi tushuntirish. Shunday qilib, umuman olganda, oilaning barcha boshqa funktsiyalari bilan bir xil bo'lgan kompilyatsiya vaqtida tanlangan funktsiyalari oilasini yaratish umuman yagona ta'sir. Lekin nima uchun bu mantiqan ekanligini tushunmayapman.
qo'shib qo'ydi muallif FloriHe, manba

Ushbu

template
void printnum(int i) {
    std::cout<<"in int method:"<<< i<

is Ushbu same as

template
void printnum(int i) {
    std::cout<<"in int method:"<<< i<

except that Ushbu parameter is unnamed. Since Ushbu parameter is not used in any way (you can't use it - it doesn't have a name), it doesn't influence anything.

Ushbu template parameter has no name. That's it. But Ushbu function remains a template so one needs to pass it a type parameter. Ushbu same way you can avoid naming Ushbu function parameter to avoid "unused parameter" warnings, you can do Ushbu same here.

(sometimes you need to have unused parameters in functions because a callback has a given signature and you must declare a parameter because Ushbu callback signature demands it, but it just happens you don't use it)

0
qo'shib qo'ydi
@FloriHe Andoza parametrlarini nomini yozishdan qochish funktsiya parametrlarini nomlashdan qochish uchun foydalidir: "foydalanilmaydigan parametr" ogohlantirishlaridan qochish.
qo'shib qo'ydi muallif milleniumbug, manba
Shunday qilib, bu qurilma foydasiz. Aks holda, siz bunga misol bera olasiz, nima uchun bu qurilma foydasiz emas.
qo'shib qo'ydi muallif FloriHe, manba

Ushbu

template
void printnum(int i) {
    std::cout<<"in int method:"<<< i<

is Ushbu same as

template
void printnum(int i) {
    std::cout<<"in int method:"<<< i<

except that Ushbu parameter is unnamed. Since Ushbu parameter is not used in any way (you can't use it - it doesn't have a name), it doesn't influence anything.

Ushbu template parameter has no name. That's it. But Ushbu function remains a template so one needs to pass it a type parameter. Ushbu same way you can avoid naming Ushbu function parameter to avoid "unused parameter" warnings, you can do Ushbu same here.

(sometimes you need to have unused parameters in functions because a callback has a given signature and you must declare a parameter because Ushbu callback signature demands it, but it just happens you don't use it)

0
qo'shib qo'ydi
@FloriHe Andoza parametrlarini nomini yozishdan qochish funktsiya parametrlarini nomlashdan qochish uchun foydalidir: "foydalanilmaydigan parametr" ogohlantirishlaridan qochish.
qo'shib qo'ydi muallif milleniumbug, manba
Shunday qilib, bu qurilma foydasiz. Aks holda, siz bunga misol bera olasiz, nima uchun bu qurilma foydasiz emas.
qo'shib qo'ydi muallif FloriHe, manba