මට “අච්චුව” සහ “යතුරු ලියනය” යන වචන තැබිය යුත්තේ කොතැනද සහ ඇයි?


1148

සැකිලි වලදී, මා තැබිය යුත්තේ කොතැනද සහ ඇයි typenameසහ templateයැපෙන නම් මත?
කෙසේ වෙතත් යැපෙන නම් හරියටම කුමක්ද?

මට පහත කේතය ඇත:

template <typename T, typename Tail> // Tail will be a UnionNode too.
struct UnionNode : public Tail {
    // ...
    template<typename U> struct inUnion {
        // Q: where to add typename/template here?
        typedef Tail::inUnion<U> dummy; 
    };
    template< > struct inUnion<T> {
    };
};
template <typename T> // For the last node Tn.
struct UnionNode<T, void> {
    // ...
    template<typename U> struct inUnion {
        char fail[ -2 + (sizeof(U)%2) ]; // Cannot be instantiated for any U
    };
    template< > struct inUnion<T> {
    };
};

මට තිබෙන ගැටලුව තිබෙන්නේ typedef Tail::inUnion<U> dummyරේඛාව තුළයි. inUnionඑය යැපෙන නමක් බව මට තරයේ විශ්වාසයි, සහ VC ++ එය මත හුස්ම ගැනීමේදී හරි ය. InUnion යනු අච්චු-හැඳුනුම්පතක් බව සම්පාදකයාට පැවසීමට මට කොතැනක හෝ
එකතු කළ හැකි බව මම දනිමි template. නමුත් හරියටම කොහෙද? ඉන් පසුව යුනියන් යනු පන්ති අච්චුවක් යැයි උපකල්පනය කළ යුතුද, එනම් inUnion<U>වර්ගයක් නම් කරන අතර එය ශ්‍රිතයක් නොවේද?


1
කරදරකාරී ප්‍රශ්නය: ඇයි වැඩි නොකරන්නේ :: ප්‍රභේදය?
අසාෆ් ලාවි

59
දේශපාලන සංවේදීතාවන්, අතේ ගෙන යා හැකි බව.
MSalters

5
මම ඔබේ සත්‍ය ප්‍රශ්නය ("අච්චුව / ටයිප් නාමය තැබිය යුත්තේ කොතැනටද?") ආරම්භයේ දී අවසාන ප්‍රශ්නය සහ කේතය තැබීමෙන් වඩා කැපී පෙනෙන අතර 1024x තිරයකට ගැලපෙන පරිදි කේතය තිරස් අතට කෙටි කළෙමි.
ජොහැන්නස් ෂෝබ් -

7
මාතෘකාවෙන් "යැපෙන නම්" ඉවත් කරන ලද්දේ "යතුරු ලියනය" සහ "අච්චුව" ගැන පුදුම වන බොහෝ අය "යැපෙන නම්" යනු කුමක්දැයි නොදන්නා බැවිනි. එය ඔවුන්ට මේ ආකාරයෙන් අඩු ව්‍යාකූල විය යුතුය.
ජොහැන්නස් ෂෝබ් - litb

2
@ එම්එස්එල්ටර්ස්: තල්ලුව තරමක් අතේ ගෙන යා හැකිය. මම කියන්නේ තල්ලුව බොහෝ විට නිරුපද්‍රිතව පැවතීමට පොදු හේතුව දේශපාලනය පමණක් බවයි. මා දන්නා එකම හොඳ හේතුව වන්නේ වැඩිවන කාලයයි. එසේ නොමැති නම් මේ සියල්ල රෝදය ප්‍රතිනිර්මාණය කිරීම සඳහා ඩොලර් දහස් ගණනක් අහිමි වීමකි.
v.oddou

Answers:


1177

( මගේ C ++ 11 පිළිතුර සඳහා ද මෙහි බලන්න )

C ++ වැඩසටහනක් විග්‍රහ කිරීම සඳහා, සම්පාදකයාට ඇතැම් නම් වර්ගද නැද්ද යන්න දැනගත යුතුය. පහත උදාහරණයෙන් එය පෙන්නුම් කරයි:

t * f;

මෙය විග්‍රහ කළ යුත්තේ කෙසේද? බොහෝ භාෂාවන් සඳහා, සම්පාදකයෙකුට නමක තේරුම විග්‍රහ කිරීමට සහ කේත රේඛාවක් කරන්නේ කුමක්දැයි දැන ගැනීමට අවශ්‍ය නොවේ. C ++ හි, කෙසේ වෙතත්, ඉහත සඳහන් කළ හැකි දේ අනුව වෙනස් අර්ථකථන ලබා දිය හැකිය t. එය වර්ගයක් නම්, එය දර්ශකයේ ප්‍රකාශයක් වනු ඇත f. කෙසේ වෙතත් එය වර්ගයක් නොවේ නම්, එය ගුණ කිරීමකි. එබැවින් C ++ ප්‍රමිතිය (3/7) ඡේදයේ මෙසේ පවසයි:

සමහර නම් වර්ග හෝ සැකිලි දක්වයි. පොදුවේ ගත් කල, නමක් හමු වූ සෑම අවස්ථාවකම එම නම එහි අඩංගු වැඩසටහනක් විග්‍රහ කිරීමට පෙර මෙම එක් ආයතනයක් නිරූපණය කරන්නේද යන්න තීරණය කිරීම අවශ්‍ය වේ. මෙය තීරණය කරන ක්‍රියාවලිය නම සෙවීම ලෙස හැඳින්වේ.

අච්චු වර්ග පරාමිතියකට යොමු කරන්නේ t::xනම්, නමක් යොමු කරන්නේ කුමක් දැයි සම්පාදකයා සොයා ගන්නේ කෙසේද t? xස්ථිතික int දත්ත සාමාජිකයෙකු විය හැකි අතර එය ගුණ කළ හැකි හෝ සමානව කැදැලි පංතියක් හෝ ප්‍රකාශනයකට යටත් විය හැකි යතුරු ලියනය කළ හැකිය. නමකට මෙම දේපල තිබේ නම් - සත්‍ය අච්චු තර්ක දැන ගන්නා තෙක් එය සොයා බැලිය නොහැකි නම් - එය යැපෙන නමක් ලෙස හැඳින්වේ (එය අච්චු පරාමිතීන් මත "රඳා පවතී").

පරිශීලකයා අච්චුව ස්ථාපනය කරන තෙක් බලා සිටීමට ඔබට නිර්දේශ කළ හැකිය:

පරිශීලකයා අච්චුව ස්ථාපනය කරන තෙක් බලා සිටිමු, පසුව එහි සැබෑ අරුත සොයා ගනිමු t::x * f;.

මෙය ක්‍රියාත්මක වන අතර ඇත්ත වශයෙන්ම ක්‍රියාත්මක කළ හැකි ප්‍රවේශයක් ලෙස සම්මතයට අවසර දෙනු ලැබේ. මෙම සම්පාදකයින් මූලික වශයෙන් අච්චුවේ පෙළ අභ්‍යන්තර බෆරයකට පිටපත් කරන අතර, ක්ෂණිකකරණයක් අවශ්‍ය වූ විට පමණක්, ඔවුන් අච්චුව විග්‍රහ කර අර්ථ දැක්වීමේ දෝෂ හඳුනා ගනී. අච්චුවේ කතුවරයා විසින් සිදුකරන ලද දෝෂයන්ගෙන් අච්චුවේ පරිශීලකයින්ට (දුප්පත් සගයන්!) කරදර කරනවා වෙනුවට, වෙනත් ක්‍රියාත්මක කිරීම් මඟින් අච්චු කල්තියාම පරීක්ෂා කර අර්ථ දැක්වීමේ දෝෂ ලබා දීමට හැකි වේ.

එබැවින් සමහර නම් වර්ග බවත් සමහර නම් එසේ නොවන බවත් සම්පාදකයාට පැවසීමට ක්‍රමයක් තිබිය යුතුය.

"යතුරු ලියනය" යතුර

පිළිතුර: සම්පාදකයා මෙය විග්‍රහ කළ යුතු ආකාරය අපි තීරණය කරමු . නම් t::xයැෙපන නම, ඉන් පසුව අපි එය උපසර්ගය කිරීමට අවශ්ය typenameඑක්තරා ආකාරයකට එය විග්රහ කළ කිරීමට සම්පාදකවරයා කියන්න. ස්ටෑන්ඩර්ඩ් (14.6 / 2) හි මෙසේ පවසයි:

අච්චු ප්‍රකාශනයක හෝ අර්ථ දැක්වීමක භාවිතා වන නමක් වන අතර එය අච්චු-පරාමිතිය මත රඳා පවතී.

typenameඅවශ්‍ය නොවන බොහෝ නම් තිබේ , මන්දයත්, සම්පාදකයාට, අච්චු අර්ථ දැක්වීමේදී අදාළ නාම සෙවීම සමඟ T *f;, ඉදිකිරීමක් විග්‍රහ කරන්නේ කෙසේදැයි සොයා ගත හැකිය - නිදසුනක් ලෙස , Tටයිප් අච්චු පරාමිතියක් සමඟ. නමුත් t::x * f;ප්‍රකාශයක් වීමට නම් එය මෙසේ ලිවිය යුතුය typename t::x *f;. ඔබ යතුරුපදය අතහැර දමා නම වර්ගයක් නොවන ලෙස සලකනු ලැබුවද, ක්ෂණිකව එය සොයාගත් විට එය වර්ගයක් දක්වයි, සුපුරුදු දෝෂ පණිවිඩ සම්පාදකයා විසින් විමෝචනය කරයි. සමහර විට, දෝෂය අර්ථ දැක්වීමේ වේලාවේදී දෙනු ලැබේ:

// t::x is taken as non-type, but as an expression the following misses an
// operator between the two names or a semicolon separating them.
t::x f;

වාක්‍ය ඛණ්ඩය ඉඩ typenameදෙන්නේ සුදුසුකම් ලත් නම් වලට පෙර පමණි - එබැවින් සුදුසුකම් නොලත් නම් සෑම විටම වර්ග වලට යොමු කිරීමට දන්නා බව සලකනු ලැබේ.

හඳුන්වාදීමේ පා by යෙන් ඉඟි කර ඇති පරිදි, සැකිලි දැක්වෙන නම් සඳහා සමාන ගොචා පවතී.

"අච්චු" යතුර

ඉහත ආරම්භක උපුටා දැක්වීම මතක තබා ගන්න සහ සම්මත සඳහා සැකිලි සඳහා විශේෂ හැසිරවීමක් අවශ්‍ය වන්නේ කෙසේද? පහත දැක්වෙන අහිංසක පෙනුමැති උදාහරණය බලමු:

boost::function< int() > f;

එය මිනිස් පා .කයෙකුට පැහැදිලිව පෙනේ. සම්පාදකයා සඳහා එසේ නොවේ. පහත සඳහන් අත්තනෝමතික අර්ථ දැක්වීම සිතන්න boost::functionහා f:

namespace boost { int function = 0; }
int main() { 
  int f = 0;
  boost::function< int() > f; 
}

එය ඇත්ත වශයෙන්ම වලංගු ප්‍රකාශනයකි ! එය සංසන්දනය කිරීමට අඩු-වඩා ක්රියාකරු භාවිතා boost::function(ශුන්ය එරෙහිව int()), හා එහි ප්රතිඵලයක් ලෙස සංසන්දනය කිරීමට පසුව වැඩි-වඩා ක්රියාකරු භාවිතා boolඑරෙහිව f. කෙසේ වෙතත් ඔබ හොඳින් දන්නා පරිදි, boost::function සැබෑ ජීවිතයේ අච්චුවක් වන බැවින් සම්පාදකයා දනී (14.2 / 3):

නම බැලීමෙන් පසු (3.4) නමක් අච්චු-නමක් බව සොයා ගත් විට, මෙම නම <අනුගමනය කරන්නේ නම්, <සෑම විටම අච්චු-තර්ක-ලැයිස්තුවක ආරම්භය ලෙස සලකනු ලබන අතර කිසි විටෙකත් අඩු- ක්රියාකරුට වඩා.

දැන් අපි නැවතත් එම ගැටලුවටම පැමිණ සිටිමු typename. කේතය විග්‍රහ කිරීමේදී නම අච්චුවක් දැයි අපට තවමත් දැනගත නොහැකි නම් කුමක් කළ යුතුද? templateනිශ්චිතව දක්වා ඇති පරිදි, අච්චුවේ නමට පෙර වහාම ඇතුළත් කිරීමට අපට අවශ්‍ය වනු ඇත 14.2/4. මෙය පෙනේ:

t::template f<int>(); // call a function template

පසු පමණක් සැකිලි සිදු විය නොහැක ::පමණක් නොව, පසු ->හෝ .පන්ති සාමාජික ප්රවේශ. ඔබ ද එහි මූලික පදය ඇතුළත් කළ යුතුය:

this->template f<int>(); // call a function template

යැපීම්

රාක්කවල Standard න ස්ටෑන්ඩර්ඩීස් පොත් ඇති සහ මා කතා කළේ හරියටම කුමක් දැයි දැන ගැනීමට අවශ්‍ය පුද්ගලයින් සඳහා, මෙය ස්ටෑන්ඩර්ඩ් හි නිශ්චිතව දක්වා ඇති ආකාරය ගැන මම ටිකක් කතා කරමි.

අච්චු ප්‍රකාශන වලදී, සමහර ඉදිකිරීම් සඳහා අච්චුව ස්ථාපනය කිරීමට ඔබ භාවිතා කරන අච්චු තර්ක මත පදනම්ව විවිධ අර්ථයන් ඇත: ප්‍රකාශනවල විවිධ වර්ග හෝ අගයන් තිබිය හැකිය, විචල්‍යයන්ට විවිධ වර්ග තිබිය හැකිය, නැතහොත් ශ්‍රිත ඇමතුම් විවිධ කාර්යයන් ඇමතීම අවසන් විය හැකිය. එවැනි ඉදිකිරීම් සාමාන්‍යයෙන් අච්චු පරාමිතීන් මත රඳා පවතී .

ප්‍රමිතියක් නිශ්චිතවම නිර්වචනය කරන්නේ ඉදිකිරීමක් රඳා පවතින්නේද නැද්ද යන්නයි. එය ඔවුන්ව තාර්කිකව විවිධ කණ්ඩායම් වලට වෙන් කරයි: එක් අයෙක් වර්ග අල්ලා ගනී, තවත් අය ප්‍රකාශන අල්ලා ගනී. ප්‍රකාශන ඒවායේ වටිනාකම සහ / හෝ ඒවායේ වර්ගය අනුව රඳා පවතී. එබැවින් සාමාන්‍ය උදාහරණ එකතු කර ඇත:

  • යැපුම් වර්ග (උදා: වර්ග අච්චු පරාමිතියක් T)
  • අගය මත රඳා පවතින ප්‍රකාශන (උදා: වර්ග නොවන අච්චු පරාමිතිය N)
  • වර්ගය මත රඳා පවතින ප්‍රකාශන (උදා: වර්ග අච්චු පරාමිතියකට වාත්තු කිරීම (T)0)

බොහෝ නීති රීති බුද්ධිමත් වන අතර ඒවා පුනරාවර්තන ලෙස ගොඩනගා ඇත: නිදසුනක් ලෙස, අගය මත රඳා පවතින ප්‍රකාශනයක් හෝ T[N]යැපෙන වර්ගයක් නම් යැපෙන වර්ගයක් ලෙස ඉදිකරන ලද වර්ගයකි. මේ පිළිබඳ විස්තර කොටසින් කියවිය හැකිය ) යැපෙන වර්ග සඳහා, වර්ගය මත පදනම් වූ ප්‍රකාශන සඳහා සහ අගය මත රඳා පවතින ප්‍රකාශන සඳහා.NT(14.6.2/1(14.6.2.2)(14.6.2.3)

යැපෙන නම්

ප්‍රමිතිය යනු හරියටම යැපෙන නමක් යනු කුමක්ද යන්න පිළිබඳව තරමක් අපැහැදිලි ය . සරල කියවීමකදී (ඔබ දන්නවා, අවම වශයෙන් පුදුම කිරීමේ මූලධර්මය), එය යැපෙන නමක් ලෙස අර්ථ දක්වන්නේ පහත ක්‍රියාකාරී නම් සඳහා විශේෂ අවස්ථාවයි. නමුත් T::xක්ෂණික සන්දර්භය තුළ පැහැදිලිව සොයා බැලිය යුතු බැවින් එය යැපෙන නමක් ද විය යුතුය (වාසනාවකට මෙන්, සී ++ 14 මැද භාගය වන විට කමිටුව මෙම ව්‍යාකූල අර්ථ දැක්වීම නිවැරදි කරන්නේ කෙසේදැයි සොයා බැලීමට පටන් ගෙන ඇත).

මෙම ගැටළුව මඟහරවා ගැනීම සඳහා, මම සම්මත පා of යේ සරල අර්ථ නිරූපණයකට යොමු වී සිටිමි. යැපෙන වර්ග හෝ ප්‍රකාශන දැක්වෙන සියලු ඉදිකිරීම් අතුරින්, ඒවායේ උප කුලකයක් නම් නියෝජනය කරයි. එබැවින් එම නම් "යැපෙන නම්" වේ. නමකට විවිධ ස්වරූප ගත හැකිය - සම්මත පවසයි:

නමක් යනු හඳුනාගැනීමක් (2.11), ක්‍රියාකරු-ක්‍රියාකාරී-හැඳුනුම්පත (13.5), පරිවර්තනය-ක්‍රියාකාරී-හැඳුනුම්පත (12.3.2), හෝ අච්චුවක්-හැඳුනුම්පතක් (14.2), එය වස්තුවක් හෝ ලේබලයක් (6.6.4, 6.1)

හඳුනාගැනීමක් යනු අක්ෂර / ඉලක්කම්වල සරල අනුක්‍රමයක් පමණක් වන අතර ඊළඟ දෙක යනු operator +සහ operator typeස්වරූපයයි. අවසාන ස්වරූපය වේ template-name <argument list>. මේ සියල්ල නම් වන අතර, සම්මතයේ සාම්ප්‍රදායික භාවිතයෙන්, නමක් සොයා බැලිය යුතු නාම අවකාශය හෝ පන්තිය කුමක්දැයි පවසන සුදුසුකම් ඇතුළත් විය හැකිය.

අගය මත රඳා පවතින ප්‍රකාශනයක් 1 + Nනමක් නොව Nඑය වේ. සියලු යැපෙන ඉදිකිරීම් වල උප කුලකය යැපෙන නම ලෙස හැඳින්වේ . කෙසේ වෙතත්, ක්‍රියාකාරී නාමයන්ට අච්චුවක විවිධ අවස්ථා වලදී වෙනස් අර්ථයක් තිබිය හැකි නමුත් අවාසනාවකට මෙම සාමාන්‍ය රීතියට හසු නොවේ.

යැපෙන ශ්‍රිත නම්

මෙම ලිපියේ මූලික වශයෙන් සැලකිලිමත් නොවන නමුත් තවමත් සඳහන් කිරීම වටී: ක්‍රියාකාරී නම් යනු වෙන වෙනම හසුරුවන ව්‍යතිරේකයකි. හඳුනාගැනීමේ ශ්‍රිතයේ නම රඳා පවතින්නේ එය විසින්ම නොව, ඇමතුමක භාවිතා වන පරායත්ත තර්ක ප්‍රකාශන මතය. උදාහරණයක් ලෙස f((T)0), fයැපෙන නමකි. සම්මතයේ, මෙය මෙහි දක්වා ඇත (14.6.2/1).

අමතර සටහන් සහ උදාහරණ

ප්‍රමාණවත් අවස්ථාවන්හිදී අපට typenameසහ දෙකම අවශ්‍ය වේ template. ඔබේ කේතය පහත පරිදි විය යුතුය

template <typename T, typename Tail>
struct UnionNode : public Tail {
    // ...
    template<typename U> struct inUnion {
        typedef typename Tail::template inUnion<U> dummy;
    };
    // ...
};

මූල පදය templateසැමවිටම නමක අවසාන කොටසේ දිස්විය යුතු නැත. පහත දැක්වෙන උදාහරණයේ දී මෙන්, විෂය පථයක් ලෙස භාවිතා කරන පන්ති නාමයකට පෙර එය මැදින් දිස්විය හැකිය

typename t::template iterator<int>::value_type v;

සමහර අවස්ථාවල, පහත විස්තර කර ඇති පරිදි, මූලික වචන තහනම් කර ඇත

  • යැපෙන පාදක පන්තියක නමින් ඔබට ලිවීමට අවසර නැත typename. ලබා දී ඇති නම පන්ති වර්ගයේ නමක් යැයි උපකල්පනය කෙරේ. මූලික පංති ලැයිස්තුවේ සහ ඉදිකිරීම්කරු ආරම්භක ලැයිස්තුවේ නම් දෙකටම මෙය සත්‍ය වේ:

     template <typename T>
     struct derive_from_Has_type : /* typename */ SomeBase<T>::type 
     { };
  • ප්‍රකාශන භාවිතා templateකිරීමේදී අවසාන වරට භාවිතා කළ නොහැකි ::අතර C ++ කමිටුව පැවසුවේ විසඳුමක් සඳහා වැඩ නොකරන ලෙසයි.

     template <typename T>
     struct derive_from_Has_type : SomeBase<T> {
        using SomeBase<T>::template type; // error
        using typename SomeBase<T>::type; // typename *is* allowed
     };

23
මෙම පිළිතුර මා කලින් ඉවත් කළ නිති අසන ප්‍රශ්න ඇතුළත් කිරීමෙන් පිටපත් කරන ලදි, මන්ද ඒවාට පිළිතුරු සැපයීම සඳහා නව "ව්‍යාජ ප්‍රශ්න" සෑදීම වෙනුවට පවත්නා සමාන ප්‍රශ්න භාවිතා කළ යුතු බව මට පෙනී ගියේය. අවසාන කොටසේ අදහස් ( යතුරු ලියනය / අච්චුව තහනම් කර ඇති අවස්ථා) පිළිතුරට සංස්කරණය කළ ra ප්‍රසූන් වෙත ස්තූතියි .
ජොහැන්නස් ෂෝබ් - litb

1
මෙම සින්ටැක්ස් භාවිතා කළ යුත්තේ කවදාදැයි ඔබට මට උදව් කළ හැකිද? මෙම-> අච්චුව f <int> (); මට මෙම දෝෂය 'අච්චුව' (ව්‍යාකූල කරන්නෙකු ලෙස) අවසර දී ඇත්තේ සැකිලි තුළ පමණක් වන නමුත් අච්චු මූල පදය නොමැතිව එය හොඳින් ක්‍රියාත්මක වේ.
බෝල්කි

1
මම අදත් ඒ හා සමාන ප්‍රශ්නයක් ඇසුවෙමි, එය ඉතා ඉක්මනින් අනුපිටපතක් ලෙස සලකුණු විය: stackoverflow.com/questions/27923722/… . අළුත් ප්‍රශ්නයක් නිර්මාණය කරනවා වෙනුවට මෙම ප්‍රශ්නය නැවත පණ ගැන්වීමට මට උපදෙස් දෙන ලදී. ඒවා අනුපිටපත් වීම ගැන මා එකඟ නොවන බව පැවසිය යුතුය, නමුත් මම කවුද? ඉතින්, typenameමේ අවස්ථාවේ දී ටයිප්-නාම හැර වෙනත් විකල්ප අර්ථ නිරූපණයන් සඳහා සින්ටැක්ස් ඉඩ නොදෙන විට පවා බලාත්මක වන හේතුවක් තිබේද?
ජෝර්න්හයිට්

1
Ab පැබ්ලෝ ඔබට කිසිවක් මග හැරී නැත. සම්පූර්ණ රේඛාව තවදුරටත් අපැහැදිලි නොවුවද, වක්‍රෝත්තිහරණය ලිවීමට තවමත් අවශ්‍ය වේ.
ජොහැන්නස් ෂෝබ් - litb

1
Ab පැබ්ලෝ අරමුණ වන්නේ භාෂාව සහ සම්පාදකයින් සරල ලෙස තබා ගැනීමයි. ඔබට ස්වයංක්‍රීයව කාරණා හදුනා ගැනීමට වැඩි අවස්ථාවන් සඳහා ඉඩ ප්‍රස්ථා ඇත, එවිට ඔබට අඩු වාර ගණනක් අවශ්‍ය වේ. ඔබගේ නිදසුනේ, සංකේත බව සටහන වේ අපැහැදිලි සහ ඔබ දැක ඇති වූ පසු පමණක් ">" ද්විත්ව පසු, ඔබ එය සැකිලි කෝණය වරහන ලෙස disambiguate හැක. වැඩි විස්තර සඳහා, C ++ සම්පාදකයින්ගේ විග්‍රහයක් ක්‍රියාත්මක කිරීමට මට අත්දැකීම් නොමැති නිසා මම ඇසීමට වැරදි පුද්ගලයා වෙමි.
ජොහැන්නස් ෂෝබ් - litb

138

සී ++ 11

ගැටලුව

C ++ 03 හි ඇති නීති ඔබට අවශ්‍ය විටදී typenameසහ templateබොහෝ දුරට සාධාරණ වුවත්, එය සකස් කිරීමේදී එක් කරදරකාරී අවාසියක් ඇත

template<typename T>
struct A {
  typedef int result_type;

  void f() {
    // error, "this" is dependent, "template" keyword needed
    this->g<float>();

    // OK
    g<float>();

    // error, "A<T>" is dependent, "typename" keyword needed
    A<T>::result_type n1;

    // OK
    result_type n2; 
  }

  template<typename U>
  void g();
};

දැකිය හැකි පරිදි, සම්පාදකයාට පරිපූර්ණ විය A::result_typeහැකි int(සහ ඒ නිසා එය වර්ගයක්) this->gවිය හැකි වුවත්, gපසුව ප්‍රකාශයට පත් කරන ලද සාමාජික අච්චුව පමණක් විය හැකිය ( Aපැහැදිලිව කොතැනක හෝ විශේෂ specialized තාවයකින් යුක්ත වුවද ) එම අච්චුව තුළ ඇති කේතයට බලපාන්නේ නැත, එබැවින් එහි අර්ථය පසුකාලීන විශේෂීකරණයකින් බලපාන්නේ නැත A!).

වත්මන් ක්ෂණිකකරණය

තත්වය වැඩිදියුණු කිරීම සඳහා, C ++ 11 හි වර්ගයක් සංවෘත අච්චුවකට යොමු වූ විට භාෂාව ලුහුබඳිනු ඇත. බව දැන ගැනීමට, වර්ගය එහි ම නම වන නම එක්තරා ආකාරයක, (ඉහත දී භාවිතා කරන ලද්දේ නිර්මාණය වී ඇති කළ යුතුයි A, A<T>, ::A<T>). එවැනි නමකින් සඳහන් කරන ලද වර්ගය වර්තමාන ක්ෂණිකකරණය ලෙස හැඳින්වේ . එහි (එවකට, සියලු වත්මන් හිතන්න උගන්වන්න බව නම නිර්මාණය වන සිට වර්ගය සාමාජිකයෙකු / nested පන්ති නම් බහු වර්ග විය හැක A::NestedClassහා Aදෙකම වත්මන් instantiations වේ).

මෙම මතය මත පදනම්ව, භාෂාව පවසන්නේ CurrentInstantiation::Foo, Fooසහ CurrentInstantiationTyped->Foo(වැනි A *a = this; a->Foo) ඔවුන් වත්මන් ක්ෂණිකකරණයේ පන්තියේ සාමාජිකයන් බව හෝ ඔවුන්ගේ යැපීම් නොවන මූලික පංති වලින් එකක් ලෙස පෙනී යන්නේ නම් (වැනි ) නම බැලීම වහාම).

මූලික පද typenameසහ templateසුදුසුකම් දැන් වත්මන් ක්ෂණිකකරණයේ සාමාජිකයෙකු නම් තවදුරටත් අවශ්‍ය නොවේ. මතක තබා ගත යුතු ප්‍රධාන කරුණක් A<T>නම්, එය තවමත් වර්ගය මත රඳා පවතින නමකි (සියල්ලට පසු Tවර්ගය මත රඳා පවතී). නමුත් A<T>::result_typeඑය වර්ගයක් ලෙස දන්නා කරුණකි - සම්පාදකයා මෙය හඳුනා ගැනීම සඳහා මේ ආකාරයේ යැපෙන වර්ග පිළිබඳව "ඉන්ද්‍රජාලිකව" සොයා බලයි.

struct B {
  typedef int result_type;
};

template<typename T>
struct C { }; // could be specialized!

template<typename T>
struct D : B, C<T> {
  void f() {
    // OK, member of current instantiation!
    // A::result_type is not dependent: int
    D::result_type r1;

    // error, not a member of the current instantiation
    D::questionable_type r2;

    // OK for now - relying on C<T> to provide it
    // But not a member of the current instantiation
    typename D::questionable_type r3;        
  }
};

එය සිත් ඇදගන්නා සුළු ය, නමුත් අපට වඩා හොඳින් කළ හැකිද? භාෂාව තව දුරටත් ඉදිරියට යන අතර , ක්ෂණිකව ක්‍රියාත්මක කිරීමේදී නැවත වරක් ක්‍රියාත්මක කිරීම අවශ්‍ය වේ (එහි අර්ථය දැනටමත් අර්ථ දැක්වීමේ වේලාවේදී සොයාගෙන ඇතත්). දැන් බැලීමේ ප්‍රති result ලය වෙනස් වන විට හෝ නොපැහැදිලි ප්‍රති results ල ලබා දෙන විට, වැඩසටහන වැරදි ලෙස සකස් වී ඇති අතර රෝග විනිශ්චය ලබා දිය යුතුය. අප අර්ථ නම් සිදු කළ දෙය ගැන සිතා බලන්න මේ වගේD::result_typeD::fC

template<>
struct C<int> {
  typedef bool result_type;
  typedef int questionable_type;
};

ක්ෂණික කිරීමේදී දෝෂය හසු කර ගැනීම සඳහා සම්පාදකයෙකු අවශ්‍ය වේ D<int>::f. ඔබ ලබා දේද ඔබ රඳා පදනම පන්ති කරදර ලබා ගත හැකි නම්, ඔබ ආරක්ෂා විමසුම් "ප්රමාද", සහ "වහාම" විමසුම්: ඔබ ලොව දෙකක් ලබා ගැනීමට හැකි නිසා typenameසහ template.

නොදන්නා විශේෂීකරණය

කේතයේ D, නම typename D::questionable_typeවත්මන් ක්ෂණිකකරණයේ සාමාජිකයෙක් නොවේ. ඒ වෙනුවට භාෂාව එය නොදන්නා විශේෂීකරණයක සාමාජිකයෙකු ලෙස සලකුණු කරයි . විශේෂයෙන් ම, හැම විටම ඔබ කරන්නේ එම නඩුව වේ DependentTypeName::Fooහෝ DependentTypedName->Fooසහ එක්කෝ රඳා වර්ගය වේ නොහැකි වත්මන් හිතන්න උගන්වන්න (සම්පාදකවරයා අතහරින්න සහ "අප පසුව දේ බලාපොරොත්තු වනු ඇත කියන්න පුළුවන් කුමන අවස්ථාවකදී Fooවේ) හෝ එය වේ වත්මන් හිතන්න උගන්වන්න සහ එහි හෝ එහි යැපෙන්නේ නැති මූලික පංතිවල නම හමු නොවූ අතර යැපෙන මූලික පන්ති ද ඇත.

hඉහත අර්ථ දක්වා ඇති Aපන්ති අච්චුව තුළ අපට සාමාජික ශ්‍රිතයක් තිබේ නම් කුමක් සිදුවේදැයි සිතා බලන්න

void h() {
  typename A<T>::questionable_type x;
}

C ++ 03 හි, මෙම දෝෂය හසු කර ගැනීමට භාෂාවට ඉඩ දී ඇත්තේ කිසි විටෙකත් ක්ෂණික කිරීමට වලංගු ක්‍රමයක් නොමැති බැවිනි A<T>::h(ඔබ කුමන තර්කයක් ඉදිරිපත් කළත් T). C ++ 11 හි, මෙම රීතිය ක්‍රියාත්මක කිරීම සඳහා සම්පාදකයින්ට වැඩි හේතුවක් ලබා දීම සඳහා භාෂාවට දැන් තවත් පරීක්‍ෂණයක් තිබේ. සිට Aකිසිදු රඳා පදනම පංති, සහ Aකිසිදු සාමාජිකයෙකු ප්රකාශ questionable_type, නම A<T>::questionable_typeවන වත් වත්මන් හිතන්න උගන්වන්න සාමාජිකයෙකු හෝනොදන්නා විශේෂීකරණයක සාමාජිකයෙකි. එවැනි අවස්ථාවකදී, එම කේතය ක්ෂණිකව සම්පාදනය කළ හැකි ක්‍රමයක් නොතිබිය යුතුය, එබැවින් සුදුසුකම් ලත් තැනැත්තාගේ නම වත්මන් ක්ෂණිකකරණය නොදන්නා විශේෂීකරණයක සාමාජිකයෙකු හෝ වත්මන් ක්ෂණිකකරණයේ සාමාජිකයෙකු නොවීම සඳහා භාෂාව තහනම් කරයි (කෙසේ වෙතත්) , මෙම උල්ලං violation නය රෝග විනිශ්චය කිරීමට තවමත් අවශ්‍ය නොවේ).

උදාහරණ සහ වැදගත්කම

ඔබට මෙම පිළිතුර මත මෙම දැනුම අත්හදා බැලිය හැකි අතර ඉහත අර්ථ දැක්වීම් සැබෑ ලෝක උදාහරණයකින් ඔබට අර්ථවත් වේදැයි බලන්න (ඒවා එම පිළිතුරෙහි තරමක් අඩු විස්තරයකින් පුනරාවර්තනය වේ).

C ++ 11 රීති මඟින් පහත දැක්වෙන වලංගු C ++ 03 කේතය වැරදි ලෙස සකස් කර ඇත (එය C ++ කමිටුව විසින් අදහස් නොකළ නමුත් බොහෝ විට නිවැරදි නොවනු ඇත)

struct B { void f(); };
struct A : virtual B { void f(); };

template<typename T>
struct C : virtual B, T {
  void g() { this->f(); }
};

int main() { 
  C<A> c; c.g(); 
}

මෙම වලංගු C ++ 03 කේතය ක්ෂණික වේලාවට බැඳී this->fඇති A::fඅතර සියල්ල හොඳයි. සී ++ 11 කෙසේ වෙතත් එය වහාම බන්ධනය වන අතර ක්ෂණිකව ක්‍රියාත්මක වන B::fවිට දෙවරක් පරීක්ෂා කිරීම අවශ්‍ය වේ. කෙසේ වෙතත්, ක්ෂණිකව ක්‍රියාත්මක C<A>::gවන විට , ආධිපත්‍ය රීතිය අදාළ වන අතර A::fඒ වෙනුවට සොයා බැලීම සොයාගත හැකිය .


fyi - මෙම පිළිතුර මෙහි සඳහන් කර ඇත: stackoverflow.com/questions/56411114/… මෙම පිළිතුරේ බොහෝ කේත විවිධ සම්පාදකයින් සමඟ සම්පාදනය නොවේ.
ඇඩම් රැකිස්

D ඇඩම්රැකිස් උපකල්පනය කරන්නේ 2013 සිට C ++ පිරිවිතර වෙනස් වී නොමැති බවයි (මම මෙම පිළිතුර ලියූ දිනය), එවිට ඔබ ඔබේ කේතය උත්සාහ කළ සම්පාදකයින් මෙම C ++ 11 + විශේෂාංගය තවමත් ක්‍රියාත්මක නොකරයි.
ජොහැන්නස් ෂෝබ් - litb

104

පෙරවදන

මෙම ලිපිය ලිට්බ්ගේ පෝස්ටයට පහසුවෙන් කියවිය හැකි විකල්පයකි .

යටින් පවතින අරමුණ සමාන ය; "කවදාද?" සහ ඇයි?" typenameහා templateඅයදුම් කළ යුතුය.


අරමුණ කුමක් ද typenameහා template?

typenameහා templateසැකිලි ප්රකාශ විට වඩා වෙනත් තත්වයන් වල භාවිතා කළ හැකි වේ.

C ++ හි ඇතැම් සන්දර්භයන් ඇත, එහිදී සම්පාදකයාට නමක් සලකන ආකාරය පැහැදිලිව පැවසිය යුතු අතර, මෙම සියලු සන්දර්භයන්ට එක දෙයක් පොදු ය; ඒවා අවම වශයෙන් එක් අච්චු-පරාමිතියක් මත රඳා පවතී .

අර්ථ නිරූපණයෙහි අපැහැදිලි බවක් තිබිය හැකි එවැනි නම් වලට අපි යොමු කරමු; " යැපෙන නම් ".

මෙම පෝස්ට් මඟින් යැපෙන නම් සහ ප්‍රධාන වචන දෙක අතර සම්බන්ධතාවයට පැහැදිලි කිරීමක් ලබා දෙනු ඇත .


ස්නිපටයක් වචන 1000 කට වඩා පවසයි

පහත දැක්වෙන ක්‍රියාකාරී අච්චුවේ සිදුවන්නේ කුමක්ද යන්න ඔබටම, මිතුරෙකුට හෝ සමහර විට ඔබේ බළලාට පැහැදිලි කිරීමට උත්සාහ කරන්න ; ( ) සලකුණු කර ඇති ප්‍රකාශයේ සිදුවන්නේ කුමක්ද?

template<class T> void f_tmpl () { T::foo * x; /* <-- (A) */ }


එය යමෙකු සිතන තරම් පහසු නොවනු ඇත, වඩාත් නිශ්චිතවම ( A ) තක්සේරු කිරීමේ ප්‍රති result ලය අච්චු-පරාමිතිය ලෙස සම්මත කරන ලද වර්ගය අර්ථ දැක්වීම මත බෙහෙවින් රඳා පවතීT .

විවිධ Ts වලට සම්බන්ධ වන අර්ථ නිරූපණයන් විශාල ලෙස වෙනස් කළ හැකිය.

struct X { typedef int       foo;       }; /* (C) --> */ f_tmpl<X> ();
struct Y { static  int const foo = 123; }; /* (D) --> */ f_tmpl<Y> ();


වෙනස් අවස්ථා දෙක :

  • ( C ) හි මෙන්, අපි X- වර්ගය සමඟ ශ්‍රිත අච්චුව ස්ථාපනය කළහොත්, අපට x නම් වූ දර්ශකයේ සිට int දක්වා ප්‍රකාශයක් ලැබෙනු ඇත , නමුත්;

  • අපි වර්ගය සමග සැකිල්ල instantiate නම් Y , (දී මෙන් ඩී ), ( ) වෙනුවට නිෂ්පාදන ගණනය බව ප්රකාශනයක් කින් සමන්විත වේ 123 සමහර සමඟ ගුණ දැනටමත් විචල්ය ප්රකාශ x .



තාර්කිකත්වය

C ++ ප්‍රමිතිය අපගේ ආරක්ෂාව සහ යහපැවැත්ම ගැන සැලකිලිමත් වේ, අවම වශයෙන් මේ අවස්ථාවේ දී.

, ප්රමිති බලතල අපි ආකාරයක වූ අර්ථ ශුන්ය සිදු වීමේ හැකියාවක් සහිත මොහොත, විස්මයන් පෙළෙන සිට ක්රියාත්මක කිරීම වැළැක්වීම සඳහා රඳා-නම විසින් පැහැදිලිව ම අපි එක්කෝ ලෙස නම ප්රතිකාර කිරීමට කැමති අරමුණ ඕනෑම තැනක පවසමින් වර්ගය-නම , හෝ template- id .

කිසිවක් ප්‍රකාශ කර නොමැති නම්, යැපෙන නම විචල්‍යයක් හෝ ශ්‍රිතයක් ලෙස සලකනු ලැබේ.



යැපෙන නම් හැසිරවිය යුත්තේ කෙසේද?

මෙය හොලිවුඩ් චිත්‍රපටයක් නම්, යැපෙන නම් යනු ශරීර සම්බන්ධතා හරහා පැතිරෙන රෝගයක් වන අතර එය ව්‍යාකූල වීමට ක්ෂණිකව එහි සත්කාරක සමාගමට බලපායි. වැරදි ලෙස සැකසූ පර්සෝ- erhm .. වැඩසටහනකට තුඩු දිය හැකි ව්‍යාකූලත්වය.

රඳා-නම වේ ඕනෑම ඍජුව නම, හෝ වක්රව, මත රඳා පවතී template-පරාමිතිය .

template<class T> void g_tmpl () {
   SomeTrait<T>::type                   foo; // (E), ill-formed
   SomeTrait<T>::NestedTrait<int>::type bar; // (F), ill-formed
   foo.data<int> ();                         // (G), ill-formed    
}

ඉහත ස්නිපටයේ අපට යැපෙන නම් හතරක් ඇත:

  • )
    • "වර්ගය" රඳා පවතින්නේ SomeTrait<T>, ඇතුළත් වන T, සහ;
  • )
    • "NestedTrait" ගිය අතර එය, සැකිල්ල-id , මත රඳා පවතී SomeTrait<T>, හා,
    • ( F ) අවසානයේ “වර්ගය” රඳා පවතින්නේ නෙස්ටෙඩ් ට්‍රේට් මත වන අතර එය රඳා පවතින්නේ SomeTrait<T>සහ;
  • )
    • සාමාජික-ක්‍රියාකාරී අච්චුවක් මෙන් පෙනෙන "දත්ත" වක්‍රව යැපෙන නමකි, මන්ද foo වර්ගය ක්ෂණිකව රඳා පවතී SomeTrait<T>.

සම්පාදකයා විසින් යැපෙන නම් විචල්‍යයන් / ශ්‍රිත ලෙස අර්ථකථනය කරන්නේ නම් ප්‍රකාශය ( ), ( එෆ් ) හෝ ( ජී ) වලංගු නොවේ (කලින් සඳහන් කළ පරිදි අප වෙනත් ආකාරයකින් පැහැදිලිව නොකියන්නේ නම් කුමක් සිදුවේද).

විසඳුම

කිරීමට g_tmplවලංගු අර්ථ දැක්වීම අප ඉතා පැහැදිලිවම අප (දී වර්ගය බලාපොරොත්තු වන බව සම්පාදකවරයා කියන්න ඕනේ ඇති ), එය සැකිල්ල-id සහ වර්ගය (දී එෆ් අ), සහ සැකිල්ල-id (දී ජී .)

template<class T> void g_tmpl () {
   typename SomeTrait<T>::type foo;                            // (G), legal
   typename SomeTrait<T>::template NestedTrait<int>::type bar; // (H), legal
   foo.template data<int> ();                                  // (I), legal
}

නමක් වර්ගයක් දැක්වෙන සෑම අවස්ථාවකම , ඊට සම්බන්ධ සියලු නම් වර්ග-නම් හෝ නාම අවකාශ විය යුතුය , මෙය මනසේ තබාගෙන typenameඅපගේ සම්පුර්ණ සුදුසුකම් ලත් නාමයේ ආරම්භයේදීම අප අයදුම් කරන බව දැකීම පහසුය .

templateකෙසේ වෙතත්, මේ සම්බන්ධයෙන් වෙනස් ය, මන්ද නිගමනයකට එළඹීමට ක්‍රමයක් නොමැති නිසා; "ඔහ්, මෙය අච්චුවකි, එවිට මෙම අනෙක් දේ ද අච්චුවක් විය යුතුය" . මෙයින් අදහස් කරන්නේ අප එවැනි ලෙස සැලකීමට කැමති templateඕනෑම නමක් ඉදිරියේ කෙලින්ම අයදුම් කරන බවයි.



මට ඕනෑම නමක් ඉදිරියේ මූල පද ඇලවිය හැකිද?

" වේවැල් මම ඇලුම් typenameහා template? කිසියම් නමක් ඉදිරිපිට මම ඔවුන් පෙනී කරන සන්දර්භය ගැන කරදර වෙන්න අවශ්ය වෙන්නේ නෑ ... " -Some C++ Developer

ඔබ සුදුසුකම් ලත් නමක් ( K ) සමඟ කටයුතු කරන තාක් කල් ඔබට මූල පද යෙදිය හැකි බව සම්මතයේ නීතිරීති වල සඳහන් වේ , නමුත් නම සුදුසුකම් නොමැති නම් යෙදුම වැරදි ලෙස සකස් වී ඇත ( L ).

namespace N {
  template<class T>
  struct X { };
}

         N::         X<int> a; // ...  legal
typename N::template X<int> b; // (K), legal
typename template    X<int> c; // (L), ill-formed

සටහන : අයදුම් කිරීම typenameහෝ templateඅවශ්‍ය නොවන සන්දර්භයක් තුළ එය හොඳ පුරුද්දක් ලෙස නොසැලකේ; ඔබට යමක් කළ හැකි නිසා, ඔබ කළ යුතු යැයි අදහස් නොකෙරේ.


මීට අමතරව එහිදී සන්දර්භයන් ඇත typenameහා templateඇත සුවිශේෂව භව්ය ලෙසින්:

  • පංතියකට උරුම වන පදනම් නියම කිරීමේදී

    ව්‍යුත්පන්න පංතියේ පාදක-පිරිවිතර-ලැයිස්තුවේ ලියා ඇති සෑම නමක්ම දැනටමත් වර්ග නාමයක් ලෙස සලකනු ලැබේ , පැහැදිලිවම සඳහන් typenameකිරීම වැරදි ලෙස සකස් කර ඇති අතර අතිරික්ත වේ.

                        // .------- the base-specifier-list
      template<class T> // v
      struct Derived      : typename SomeTrait<T>::type /* <- ill-formed */ {
        ...
      };

  • වූ විට template-id වූ ව්යුත්පන්න පන්තියේ ඇ බලතල කාර, ලබන එක් භාවිතා-නියෝගයක්

      struct Base {
        template<class T>
        struct type { };
      };
    
      struct Derived : Base {
        using Base::template type; // ill-formed
        using Base::type;          // legal
      };

1
කැපිටල් අකුරුවල ලිවීමේ ශීර්ෂයන් ඔබ තබා ගන්නේ ඇයි?
Sapphire_Brick

21

මෙම පිළිතුර මාතෘකාවේ ප්‍රශ්නයට (කොටසක්) පිළිතුරු දීමට තරමක් කෙටි හා මිහිරි එකක් විය යුතුය. ඔබට ඒවා එහි තැබිය යුත්තේ ඇයිද යන්න පැහැදිලි කරන පිළිතුරක් අවශ්‍ය නම් කරුණාකර මෙහි යන්න .


typenameමූලික පදය තැබීමේ සාමාන්‍ය රීතිය බොහෝ විට ඔබ අච්චු පරාමිතියක් භාවිතා කරන අතර ඔබට කූඩුවකට typedefහෝ අන්වර්ථයක් භාවිතා කිරීමට අවශ්‍ය වේ , උදාහරණයක් ලෙස:

template<typename T>
struct test {
    using type = T; // no typename required
    using underlying_type = typename T::type // typename required
};

මෙටා ශ්‍රිත සඳහා හෝ සාමාන්‍ය අච්චු පරාමිතීන් ගන්නා දේවල් සඳහා ද මෙය අදාළ වන බව සලකන්න. කෙසේ වෙතත්, ලබා දී ඇති අච්චු පරාමිතිය පැහැදිලි වර්ගයක් නම් ඔබ සඳහන් කළ යුතු නැත typename, උදාහරණයක් ලෙස:

template<typename T>
struct test {
    // typename required
    using type = typename std::conditional<true, const T&, T&&>::type;
    // no typename required
    using integer = std::conditional<true, int, float>::type;
};

templateව්‍යුහාත්මක / පන්තියක සැකසූ සාමාජික ක්‍රියාකාරකම් (ස්ථිතික හෝ වෙනත් ආකාරයකින්) ඇතුළත් කර ඇත්නම් හැර , සුදුසුකම් එකතු කිරීම සඳහා වන සාමාන්‍ය නීති බොහෝ දුරට සමාන වේ, උදාහරණයක් ලෙස:

මෙම ව්‍යුහය හා ක්‍රියාකාරිත්වය අනුව:

template<typename T>
struct test {
    template<typename U>
    void get() const {
        std::cout << "get\n";
    }
};

template<typename T>
void func(const test<T>& t) {
    t.get<int>(); // error
}

t.get<int>()ශ්‍රිතය ඇතුළත සිට ප්‍රවේශ වීමට උත්සාහ කිරීම දෝෂයක් වනු ඇත:

main.cpp:13:11: error: expected primary-expression before 'int'
     t.get<int>();
           ^
main.cpp:13:11: error: expected ';' before 'int'

මේ අනුව මෙම සන්දර්භය තුළ ඔබට templateපෙර පදය අවශ්‍ය වන අතර එය එසේ අමතන්න:

t.template get<int>()

එමඟින් සම්පාදකයා මෙය නිසියාකාරව විග්‍රහ කරනු ඇත t.get < int.


20
typedef typename Tail::inUnion<U> dummy;

කෙසේ වෙතත්, ඔබ inUnion ක්‍රියාත්මක කිරීම නිවැරදි යැයි මට විශ්වාස නැත. මා නිවැරදිව තේරුම් ගන්නේ නම්, මෙම පංතිය ක්ෂණිකව කළ යුතු නොවේ, එබැවින් "අසමත්" ටැබය කිසි විටෙකත් අසාර්ථක නොවනු ඇත. වර්ගය සමිතියේ තිබේද නැද්ද යන්න සරල බූලියන් අගයක් සහිතද යන්න දැක්වීම වඩා හොඳ විය හැකිය.

template <typename T, typename TypeList> struct Contains;

template <typename T, typename Head, typename Tail>
struct Contains<T, UnionNode<Head, Tail> >
{
    enum { result = Contains<T, Tail>::result };
};

template <typename T, typename Tail>
struct Contains<T, UnionNode<T, Tail> >
{
    enum { result = true };
};

template <typename T>
struct Contains<T, void>
{
    enum { result = false };
};

PS: බූස්ට් :: ප්‍රභේදය දෙස බලන්න

PS2: යතුරු ලියනය දෙස බලන්න , විශේෂයෙන් ඇන්ඩ්‍රි ඇලෙක්සැන්ඩ්‍රෙස්කුගේ පොතේ: නූතන සී ++ නිර්මාණය


උදාහරණයක් ලෙස යූනියන් <float, bool> :: operator = (U) සමඟ U == int සමඟ ඇමතීමට උත්සාහ කළහොත් inUnion <U> ක්ෂණිකව ක්‍රියාත්මක වේ. එය පුද්ගලික කට්ටලයක් (U, inUnion <U> * = 0) ලෙස හැඳින්වේ.
MSalters

ප්‍රති result ලය = සත්‍ය / අසත්‍යය සමඟ වැඩ කිරීම මට අපේ වර්තමාන OSX මෙවලම් කට්ටලයට නොගැලපෙන බූස්ට් :: enable_if <> අවශ්‍ය වේ. වෙනම අච්චුව තවමත් හොඳ අදහසකි.
MSalters

ලූක් යන්නෙන් ටයිප් කළ වලිගය :: inUnion <U> ව්‍යාජ; රේඛාව. එය වලිගය ක්ෂණික කරයි. නමුත් යුනියන් <U> නොවේ. එය පිළිබඳ සම්පූර්ණ අර්ථ දැක්වීම අවශ්‍ය වූ විට එය ක්ෂණිකව ලබා ගනී. උදාහරණයක් ලෙස ඔබ විශාලත්වය ගන්නේ නම් හෝ සාමාජිකයෙකුට ප්‍රවේශ වන්නේ නම් (:: foo භාවිතා කරමින්). Als සැල්ටර්ස් කෙසේ වෙතත්, ඔබට තවත් ගැටලුවක් තිබේ:
ජොහැන්නස් ෂෝබ් - litb

-sizeof (U) කිසි විටෙකත් negative ණ නොවේ :) මන්ද size_t යනු අත්සන් නොකළ පූර්ණ සංඛ්‍යා වර්ගයකි. ඔබට ඉතා ඉහළ සංඛ්‍යාවක් ලැබෙනු ඇත. ඔබට බොහෝ විට ප්‍රමාණයේ (U)> = 1 කිරීමට අවශ්‍යද? -1: 1 හෝ ඊට සමාන :)
ජොහැන්නස් ෂෝබ් - litb

මම එය නිර්වචනය නොකර එය ප්‍රකාශ කරමි: අච්චුව <යතුරු නාමය U> struct inUnion; එබැවින් එය ක්ෂණිකව කළ නොහැකිය. මම හිතනවා sizeof එය සහිත, සම්පාදක ඔබ දෝෂයක් දෙන්න ඔබ පවා නම් අවසර ඇත නොහැකි එය instantiate නිසා sizeof දන්නේ නම් (U) සෑම විටම> = 1 වන අතර, ...
ජොහැන්නස් Schaub - litb

2

මම මෙම විෂය පිළිබඳව කියවා ඇති වඩාත්ම සංක්ෂිප්ත පැහැදිලි කිරීම වන බැවින්, cplusplus.com වෙතින් සමාන ප්‍රශ්නයක් සඳහා ජේ.එල්.බෝර්ජස්ගේ විශිෂ්ට ප්‍රතිචාරය ඉදිරිපත් කරමි.

අප ලියන අච්චුවක, භාවිතා කළ හැකි නම් වර්ග දෙකක් තිබේ - යැපෙන නම් සහ යැපෙන්නන් නොවන නම්. යැපෙන නමක් යනු අච්චු පරාමිතියක් මත රඳා පවතින නමකි; අච්චු පරාමිතීන් කුමක් වුවත් රඳා නොපවතින නමකට එකම අර්ථයක් ඇත.

උදාහරණයක් වශයෙන්:

template< typename T > void foo( T& x, std::string str, int count )
{
    // these names are looked up during the second phase
    // when foo is instantiated and the type T is known
    x.size(); // dependant name (non-type)
    T::instance_count ; // dependant name (non-type)
    typename T::iterator i ; // dependant name (type)
      
    // during the first phase, 
    // T::instance_count is treated as a non-type (this is the default)
    // the typename keyword specifies that T::iterator is to be treated as a type.

    // these names are looked up during the first phase
    std::string::size_type s ; // non-dependant name (type)
    std::string::npos ; // non-dependant name (non-type)
    str.empty() ; // non-dependant name (non-type)
    count ; // non-dependant name (non-type)
}

යැපෙන නමකින් අදහස් කරන්නේ අච්චුවේ එක් එක් වෙනස් කිරීම සඳහා වෙනස් දෙයක් විය හැකිය. එහි ප්‍රති consequ ලයක් ලෙස C ++ සැකිලි "ද්වි-අදියර නාම සෙවීම" ට යටත් වේ. අච්චුවක් මුලින් විග්‍රහ කරන විට (කිසියම් ක්ෂණික සිදුවීමක් සිදුවීමට පෙර) සම්පාදකයා රඳා නොපවතින නම් සොයා බලයි. අච්චුවේ නිශ්චිත ක්ෂණික ක්‍රියාවලියක් සිදු වූ විට, අච්චු පරාමිතීන් ඒ වන විට දන්නා අතර සම්පාදකයා යැපෙන නම් සොයයි.

පළමු අදියරේදී, යැපෙන නමක් යනු වර්ගයක නමක්ද නැතිනම් වර්ගයක නොවන නමක්ද යන්න පාර්සර් දැනගත යුතුය. පෙරනිමියෙන්, යැපෙන නමක් වර්ග නොවන අයගේ නමක් ලෙස උපකල්පනය කෙරේ. යැපෙන නමකට පෙර යතුරු ලියන යතුරු පදය එය වර්ගයක නම බව සඳහන් කරයි.


සාරාංශය

ඔබට ටයිප් නාමයක් යතුරු පුවරුවේ ප්‍රකාශන සහ අර්ථ දැක්වීම් වල පමණක් භාවිතා කරන්න, ඔබට සුදුසුකම් ලත් නමක් තිබේ නම් එය වර්ගයක් ගැන සඳහන් වන අතර එය අච්චු පරාමිතියක් මත රඳා පවතී.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.