Mønstre med enable_if
Begrens maler på den klassiske måten
Mønstre med enable_if er en gratis leksjon i C++ Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i C++ Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i C++ Academy inneholder totalt 4 leksjoner.
Hva er enable_if
std::enable_if er en liten egenskap som betinget definerer et type-medlem. Når betingelsen er sann, finnes typen; når den er usann, fjernes den omsluttende malen via SFINAE.
- Finnes i
<type_traits>. - Er det klassiske verktøyet for å begrense maler.
#include <iostream>
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
doubleIt(T v) { return v * 2; }
int main() {
std::cout << doubleIt(21) << '\n';
return 0;
}Slik fungerer det
enable_if<Cond, T>::type er T bare når Cond er sann. Hvis den er usann, finnes det ikke noe type-medlem, og substitusjonen mislykkes.
#include <iostream>
#include <type_traits>
int main() {
std::cout << std::boolalpha;
std::cout << std::is_same<std::enable_if<true, int>::type, int>::value << '\n';
return 0;
}enable_if i returtypen
Den vanligste plasseringen er i returtypen. Funksjonen eksisterer bare når betingelsen er oppfylt.
#include <iostream>
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
half(T v) { return v / 2; }
int main() {
std::cout << half(5.0) << '\n';
return 0;
}enable_if som malparameter
Et annet uttrykksmønster plasserer enable_if i en malparameter med standardverdi, slik at returtypen forblir ryddig.
#include <iostream>
#include <type_traits>
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
T triple(T v) { return v * 3; }
int main() {
std::cout << triple(4) << '\n';
return 0;
}Snarveien enable_if_t
C++14 introduserte aliaset std::enable_if_t<Cond, T>, slik at De kan unngå støyen fra typename ...::type.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, T>
negate(T v) { return -v; }
int main() {
std::cout << negate(8) << '\n';
return 0;
}Kombinere to overlastinger
Definer komplementære betingelser slik at nøyaktig én overlasting er gyldig for enhver type, uten tvetydighet.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, const char*>
category() { return "integer"; }
template <typename T>
std::enable_if_t<!std::is_integral<T>::value, const char*>
category() { return "non-integer"; }
int main() {
std::cout << category<int>() << ' ' << category<double>() << '\n';
return 0;
}Kombinere betingelser
Bruk logiske operatorer på egenskapsverdier for å uttrykke mer omfattende begrensninger, for eksempel «heltallig og fortegnet».
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, T>
magnitude(T v) { return v < 0 ? -v : v; }
int main() {
std::cout << magnitude(-12) << '\n';
return 0;
}Begrense en konstruktør
De kan plassere enable_if på en konstruktørs malparameter for å tillate konstruktøren bare for kompatible typer.
#include <iostream>
#include <type_traits>
struct Wrapper {
int value;
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
Wrapper(T v) : value(static_cast<int>(v)) {}
};
int main() {
Wrapper w(42);
std::cout << w.value << '\n';
return 0;
}Fallgruven med standardargumenter for maler
To overlastinger som bare skiller seg ved en malparameter med standardverdien enable_if, blir oppfattet som redefinisjoner. Gi dem ulike former, for eksempel ved å plassere én betingelse i returtypen.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
printKind() { std::cout << "int\n"; }
template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
printKind() { std::cout << "float\n"; }
int main() {
printKind<int>();
printKind<double>();
return 0;
}Sammenligning med konsepter
Konsepter i C++20 erstatter det meste av bruken av enable_if med en langt tydeligere syntaks, men enable_if er fortsatt nødvendig i kode før C++20 og i enkelte spesialtilfeller.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_arithmetic<T>::value, T>
square(T v) { return v * v; }
int main() {
std::cout << square(6) << ' ' << square(1.5) << '\n';
return 0;
}Et komplett eksempel
Kombiner alt: en funksjonsfamilie som formaterer heltall og flyttall forskjellig, valgt ved kompilering.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
format(T v) { std::cout << "int[" << v << "]\n"; }
template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
format(T v) { std::cout << "float(" << v << ")\n"; }
int main() {
format(10);
format(3.5);
return 0;
}Hurtigsjekk
Test forståelsen av enable_if.
Oppsummering
De har lært de klassiske enable_if-mønstrene:
- definerer
::typebare når betingelsen er sann, slik at SFINAE aktiveres - plasseres i returtypen eller i en malparameter med standardverdi
- bruk aliaset
enable_if_tog kombiner egenskaper med logiske operatorer - konsepter har erstattet dette i C++20, men det brukes fortsatt mye
Dette avslutter kurset i malspesialisering og SFINAE.
Lær deg C++ med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 51
- Leksjoner
- 203
Ofte stilte spørsmål
Er leksjonen «Mønstre med enable_if» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien C++ Academy, inkludert «Mønstre med enable_if», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i C++ Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Mønstre med enable_if»?
Begrens maler på den klassiske måten Du øver på C++ Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med C++ Academy?
Ingen tidligere erfaring er nødvendig. C++ Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.
Hvor lang tid tar leksjonen «Mønstre med enable_if»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne C++ Academy-leksjonen?
Ja. Alle C++ Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Full spesialisering
- Delvis spesialisering
- SFINAE
- Mønstre med enable_if