( මගේ 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]
යැපෙන වර්ගයක් නම් යැපෙන වර්ගයක් ලෙස ඉදිකරන ලද වර්ගයකි. මේ පිළිබඳ විස්තර කොටසින් කියවිය හැකිය ) යැපෙන වර්ග සඳහා, වර්ගය මත පදනම් වූ ප්රකාශන සඳහා සහ අගය මත රඳා පවතින ප්රකාශන සඳහා.N
T
(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
};