C ++ 17 á móti C ++ 14 - ef-constexpr

Við erum spennt að sjá að ef-constexpr komst yfir í C ​​++ 17. Þú getur prófað það sjálfur með því að nota núverandi skottinu af clang.

Í þessari bloggfærslu skoðum við einhvern C ++ 14 kóða og reynum að nota nýja aðgerðina.

Ekki hafa if-constexpr til ráðstöfunar, þú þarft oft að grípa til vandaðra metaforritunaraðferða, nota sniðmátamynstri, ofhleðsla og SFINAE.

Dæmi 1 - að fá n-arg

Mörg meta-forrit sniðmát starfa á mismunandi tegundum listum. Í C ++ 14 er oft komið á eftirfarandi hátt að fá níundu gerð rifrildalista:

sniðmát <óundirritað n>
struct Arg {
 sniðmát 
 constexpr farartæki () (X x, Xs… xs) {
   skila Arg  {} (xs…);
 }
};
sniðmát <>
struct Arg <0> {
 sniðmát 
 constexpr farartæki () (X x, Xs ...) {
   skila x;
 }
};
sniðmát <óundirritað n>
constexpr auto arg = Arg  {};
// arg <2> (0,1,2,3,4,5) == 2;

C ++ 17 gerir þetta aðeins innsæi:

sniðmát <óundirritað n>
strukt Fáðu {
 sniðmát 
 constexpr farartæki () (X x, Xs… xs) {
   ef constexpr (n> sizeof… (xs)) {
     snúa aftur;
   } annað ef constexpr (n> 0) {
     skila Fáðu  {} (xs ...);
   } Annar {
     skila x;
   }
 }
};

Dæmi 2 - API - shimming

Stundum viltu styðja annað API. C ++ 14 er auðveld leið til að athuga hvort hægt sé að nota hlut á ákveðinn hátt:

sniðmát 
constexpr farartæki styðurAPI (T x) -> decltype (x.Method1 (), x.Method2 (), true_type {}) {
 skila {};
}
constexpr farartæki styðurAPI (…) -> falsgerð {
 skila {};
}

Það er hægt að framkvæma sérsniðna hegðun í C ++ 14:

sniðmát 
sjálfvirk útreikningur (T x) -> decltype (enable_if_t  {}) {
 skila x.Metod ();
}
sniðmát 
sjálfvirk útreikningur (T x) -> decltype (enable_if_t  {}) {
 skila 0;
}

C ++ 17:

sniðmát 
int reikni (T x) {
 ef constexpr (styðurAPI (T {})) {
   // verður aðeins tekið saman ef skilyrðið er satt
   skila x.Metod ();
 } Annar {
   skila 0;
 }
}

Þetta er mjög þægilegt þar sem kóða sem tilheyrir merkingarlega saman er ekki dreifður um margar aðgerðir. Ennfremur geturðu jafnvel skilgreint lambdas sem inniheldur if-constexpr.

Dæmi 3 - Taka saman tíma reiknirit

Oft þarf að finna besta reiknirit byggt á mengi reglna og eiginleika. Það eru margar lausnir. Til dæmis notar STL TypeTags til að velja réttan reiknirit fyrir suma gefna endurtekninga.

struct FooTag {};
struct BarTag {};
sjálfvirk foldFF (…) {}
sjálfvirk foldFB (…) {}
auto foldBF (…) {}
sjálfvirk foldBB (…) {}
strúktúr A {
 / *… * /
 með tag = FooTag;
};
strúktúr B {
 / *… * /
 með tag = BarTag;
};
sniðmát 
sjálfvirk brjóta saman (L l, R r, FooTag, BarTag) {foldFB (l, r); }
/ * fleiri sendingaraðgerðir * /
sniðmát 
sjálfvirk felling (L l, R r) {
 snúa aftur (l, r,
 typame L :: tag {},
 typame R :: tag {});
}

En þegar þú hefur flóknari reglur gætirðu þurft öflugri lausn - SFINAE:

C ++ 14:

struct BazTag: FooTag, BarTag {};
sniðmát  :: gildi &&
 is_base_of  :: gildi
> brjóta saman (L l, R r) {
 snúa afturFF (l, r);
}

Með C ++ 17 geturðu lýst þessum reglum með minni ketilplötu og á skýrari hátt:

sniðmát 
sjálfvirk felling (L l, R r) {
 nota lTag = tegund L: tag;
 að nota rTag = typame R :: tag;
ef constexpr (er_base_of  :: gildi) {
 ef constexpr (er_same  :: gildi) {
   snúa afturFF (l, r);
 } Annar {
   skila foldBB (l, r);
 } Annar {
   skila foldFF ();
 }
}

Þetta er mjög hagnýtt þar sem að vinna með ifs er innsæi en að nota margs konar lögun.

Endurgerð endurskoðunar metaföll verður eins einföld og venjulegur kóða. Með if-constexpr er áhyggjuefni fyrir óljósum of mikið og öðrum óvæntum fylgikvillum.

Við munum uppfæra þýðandann okkar um leið og Clang 3.9 er stöðugur.