C ++ 11 හි 'typedef' සහ 'භාවිතා කිරීම' අතර වෙනස කුමක්ද?


927

C ++ 11 හි අපට දැන් s usingවැනි වැනි අන්වර්ථ නාම ලිවීමට භාවිතා කළ හැකි බව මම දනිමි typedef.

typedef int MyInt;

යනු, මා තේරුම් ගත් දෙයට සමාන ය:

using MyInt = int;

එම නව වාක්‍ය ඛණ්ඩය ඉස්මතු වූයේ “ template typedef” ප්‍රකාශ කිරීමට ක්‍රමයක් තිබීමේ උත්සාහයෙන් ය :

template< class T > using MyType = AnotherType< T, MyAllocatorType >;

එහෙත්, පළමු අච්චු නොවන උදාහරණ දෙක සමඟ, ප්‍රමිතියේ වෙනත් සියුම් වෙනස්කම් තිබේද? උදාහරණයක් ලෙස, typedefඅන්වර්ථකරණය "දුර්වල" ආකාරයකින් කරන්න. එනම් එය නව වර්ගයක් නිර්මාණය නොකරන නමුත් නව නමක් පමණි (පරිවර්තනයන් එම නම් අතර ගම්‍ය වේ).

එය සමානද? usingනැතහොත් එය නව වර්ගයක් ජනනය කරයිද? වෙනස්කම් තිබේද?


221
මම පෞද්ගලිකව නව වාක්‍ය ඛණ්ඩයට වැඩි කැමැත්තක් දක්වන්නේ එය සාමාන්‍ය විචල්‍ය පැවරුමකට වඩා බොහෝ සෙයින් සමාන වන නිසා කියවීමේ හැකියාව වැඩි දියුණු කරමිනි. උදාහරණයක් ලෙස, ඔබ කැමති නැහැ typedef void (&MyFunc)(int,int);හෝ using MyFunc = void(int,int);?
මැතිව් එම්

13
මම සම්පුර්ණයෙන්ම එකඟ වෙමි, මම දැන් භාවිතා කරන්නේ නව වාක්‍ය ඛණ්ඩය පමණි. ඒකයි මම ඉල්ලුවේ, ඇත්තටම වෙනසක් නැති බව සහතික කරගන්න.
ක්ලයිම්

81
AtMatthieuM. ඒ දෙක වෙනස් btw. එය විය යුතුය typedef void MyFunc(int,int);(එය එතරම් නරක යැයි නොපෙනේ), හෝusing MyFunc = void(&)(int,int);
ආර්. මාටින්හෝ ෆර්නැන්ඩස්

5
ඔබට අවශ්ය කරන්නේ ඇයි R.MartinhoFernandes @ (සහ) ගැන using MyFunc = void(&)(int,int);? එයින් අදහස් කරන්නේ MyFuncශ්‍රිතයක් සඳහා යොමු කිරීමක් ද? ඔබ & අතහැර දැමුවහොත් කුමක් කළ යුතුද?
පොහොසත්

7
ඔව්, එය ශ්‍රිත යොමු කිරීමකි. එය සමාන වේ typedef void (&MyFunc)(int,int);. ඔබ &එය අතහැර දැමුවහොත්typedef void MyFunc(int,int);
ආර්. මාටින්හෝ ෆර්නැන්ඩස්

Answers:


14

පහත දැක්වෙන සියලුම සම්මත යොමු කිරීම් N4659: මාර්තු 2017 පශ්චාත්-කෝනා වැඩ කෙටුම්පත / සී ++ 17 ඩීඅයිඑස් .


යතුරු ලියන ප්‍රකාශයන් අන්වර්ථ ප්‍රකාශයන් ආරම්භක ප්‍රකාශ ලෙස භාවිතා කළ නොහැක

එහෙත්, පළමු අච්චු නොවන උදාහරණ දෙක සමඟ, ප්‍රමිතියේ වෙනත් සියුම් වෙනස්කම් තිබේද?

  • අර්ථකථනයේ වෙනස්කම් : කිසිවක් නැත.
  • අවසර ලත් සන්දර්භවල වෙනස්කම් : සමහර (1) .

(1) මුල් පෝස්ට් එකේ දැනටමත් සඳහන් කර ඇති අන්වර්ථ සැකිලි වල උදාහරණ වලට අමතරව .

එකම අර්ථ නිරූපණය

[Dcl.typedef] / 2 මගින් පාලනය වන පරිදි [උපුටා ගැනීම, අවධාරණය මගේ]

[dcl.typedef] / 2typedef-නම ද විසින් හඳුන්වා දිය හැක හෙවත්-ප්රකාශය . මෙම හඳුනාගැනීමේ පහත සඳහන් usingමූල පදය බවට පත් වන typedef-නම සහ විකල්ප විශේෂණය-විශේෂණයක්-මහලේකම් පා පහත සඳහන් හඳුනාගැනීමේ බව appertains typedef-නම . එවැනි යතුරු ලියනයක නමටtypedef පිරිවිතර විසින් හඳුන්වා දුන් ආකාරයටම අර්ථකථන ඇත . [...]

එය typedef-නම මගින් හඳුන්වා හෙවත්-ප්රකාශය කර එම semantics එය විසින් හඳුන්වා දෙන ලදී නම් වේ typedefප්රකාශ.

අවසර ලත් සන්දර්භයන්හි සියුම් වෙනස

කෙසේ වෙතත්, මෙම විචල්‍යයන් දෙක භාවිතා කළ හැකි සන්දර්භයන් තුළ එකම සීමාවන් ඇති බව මින් ඇඟවෙන්නේ නැත . නියත වශයෙන්ම කෙළවරේ නඩුව වුවත්, එය typedef ප්රකාශ යනු init-ප්රකාශය හා ඒ නිසා ආරම්භය ප්රකාශ ඉඩ සලසා දෙයි සන්දර්භයන් තුළ භාවිතා කළ හැකි

// C++11 (C++03) (init. statement in for loop iteration statements).
for(typedef int Foo; Foo{} != 0;) {}

// C++17 (if and switch initialization statements).
if (typedef int Foo; true) { (void)Foo{}; }
//  ^^^^^^^^^^^^^^^ init-statement

switch(typedef int Foo; 0) { case 0: (void)Foo{}; }
//     ^^^^^^^^^^^^^^^ init-statement

// C++20 (range-based for loop initialization statements).
std::vector<int> v{1, 2, 3};
for(typedef int Foo; Foo f : v) { (void)f; }
//  ^^^^^^^^^^^^^^^ init-statement

ක ෙහයින්ද, නොහොත්-ප්රකාශය වන්නේ නැත යනු init-ප්රකාශය , සහ ඒ අනුව නොවේ ආරම්භය ප්රකාශ ඉඩ සලසා දෙයි සන්දර්භයන් තුළ භාවිතා කළ

// C++ 11.
for(using Foo = int; Foo{} != 0;) {}
//  ^^^^^^^^^^^^^^^ error: expected expression

// C++17 (initialization expressions in switch and if statements).
if (using Foo = int; true) { (void)Foo{}; }
//  ^^^^^^^^^^^^^^^ error: expected expression

switch(using Foo = int; 0) { case 0: (void)Foo{}; }
//     ^^^^^^^^^^^^^^^ error: expected expression

// C++20 (range-based for loop initialization statements).
std::vector<int> v{1, 2, 3};
for(using Foo = int; Foo f : v) { (void)f; }
//  ^^^^^^^^^^^^^^^ error: expected expression

2
වාව්, මගේ බුද්ධිය අවසානයේ හරි! වෙනසක් තියෙනවා! එම වෙනස සොයා ගැනීම ගැන ස්තූතියි, එය මා සමඟ වැඩ කරන කේතයේ (අවාසනාවකට එක්ස්ඩී) වෙනසක් කළ හැකි ඉතා පටු විස්තරයකි.
ක්ලයිම්

589

සම්මතයෙන් (අවධාරණය කිරීමේ පතලේ) (7.1.3.2) ඒවා සමාන වේ:

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


24
පිළිතුරෙන්, usingමූල පදය සුපර්සෙට් එකක් ලෙස පෙනේ typedef. typdefඅනාගතයේ දී ඉවත් කරනු ලැබේ ද?
iammilind

49
ක්ෂය කිරීම අනිවාර්යයෙන්ම ඉවත් කිරීමේ අභිප්‍රාය ඇඟවුම් නොකරයි - එය හුදෙක් වෙනත් මාධ්‍යයකට වැඩි කැමැත්තක් දැක්වීම සඳහා ඉතා ප්‍රබල නිර්දේශයකි.
යකඩ ගැලවුම්කරු

18
නමුත් පසුව මම කල්පනා කරන්නේ ඔවුන් යතුරු ලියනය සැකසීමට ඉඩ නොදෙන්නේ මන්ද යන්නයි. මට මතකයි කොහේ හරි කියෙව්වා ඔවුන් usingසින්ටැක්ස් එක හරියටම හඳුන්වා දුන්නේ typedefඅර්ථකථන සැකිලි සමඟ හොඳින් ක්‍රියා නොකරන නිසා . usingඑය හරියටම එකම අර්ථකථන ඇති බවට අර්ථ දක්වා ඇති කාරණයට පටහැනි වේ.
celtschk

12
@celtschk: හේතුව යෝජනාවේ කතා කර ඇත n1489. ඒ සැකිල්ල අන්වර්ථ වේ නොහැකි වර්ගයක් සඳහා අන්වර්ථයක්, නමුත් සැකිලි කාණ්ඩයක සඳහා අන්වර්ථයක්. typedefනව වාක්‍ය ඛණ්ඩයක අවශ්‍යතාවය දැනෙන අය අතර වෙනසක් ඇති කිරීම. එසේම, OP හි ප්‍රශ්නය වන්නේ අච්චු නොවන අනුවාද අතර වෙනස ගැන ය.
ජෙසී ගුඩ්

4
ඉතින් මෙම අතිරික්තය හඳුන්වා දුන්නේ ඇයි? එකම අරමුණක් සඳහා සින්ටැක්ස් 2 ක්. මම typdefකවදාවත් අතහැර දැමූ බවක් නොපෙනේ .
බෙනොයිට්

243

ඒවා හැර ඒවා බොහෝ දුරට සමාන ය:

අන්වර්ථ ප්‍රකාශය සැකිලි සමඟ අනුකූල වේ, නමුත් C විලාසිතාවේ යතුරු ලියනය නොවේ.


29
පිළිතුරේ සරල බව සහ යතුරු ලියනයෙහි මූලාරම්භය පෙන්වා දීමට විශේෂයෙන් ප්‍රිය කරයි.
g24l

1
24 g24l ඔබ අදහස් කළේ typedef ... බොහෝ විට
Marc.2377

typedefමා ඇසුවොත් සී සහ සී ++ අතර ඇති වෙනස කුමක්ද?
මැක්සිනික්ස්

1
මෙය ප්‍රශ්නයට පිළිතුරු සපයන්නේ නැත. මම දැනටමත් එම වෙනස දන්නා අතර මුල් ලිපියේ පෙන්වා ඇත්තෙමි. මම විමසුවේ ඔබ සැකිලි භාවිතා නොකරන අවස්ථාව ගැන පමණයි, වෙනස්කම් තිබේද?
ක්ලයිම්

197

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

template <typename T> struct whatever {};

template <typename T> struct rebind
{
  typedef whatever<T> type; // to make it possible to substitue the whatever in future.
};

rebind<int>::type variable;

template <typename U> struct bar { typename rebind<U>::type _var_member; }

නමුත් භාවිතා කාරක රීති භාවිතා කොට මේ නඩුව වඩාත් සරලවන.

template <typename T> using my_type = whatever<T>;

my_type<int> variable;
template <typename U> struct baz { my_type<U> _var_member; }

37
මම දැනටමත් ප්රශ්නය තුළ මෙය පෙන්වා ඇත. මගේ ප්‍රශ්නය වන්නේ ඔබ අච්චුව භාවිතා නොකරන්නේ නම් යතුරු ලියනය සමඟ වෙනසක් තිබේද යන්නයි. උදාහරණයක් ලෙස, ඔබ 'Foo foo {init_value};' 'Foo foo (init_value)' වෙනුවට දෙදෙනාම එකම දේ කළ යුතු නමුත් එකම නීති රීති අනුගමනය නොකරන්න. ඉතින් මම කල්පනා කරමින් සිටියේ / typedef භාවිතා කිරීම හා සමාන සැඟවුණු වෙනසක් තිබේද යන්නයි.
ක්ලයිම්

23

ඒවා අත්යවශ්යයෙන්ම එකම නමුත් usingසපයයි alias templatesඉතා ප්රයෝජනවත් වන වන. මට සොයාගත හැකි එක් හොඳ උදාහරණයක් පහත පරිදි වේ:

namespace std {
 template<typename T> using add_const_t = typename add_const<T>::type;
}

ඉතින්, අපට std::add_const_t<T>ඒ වෙනුවට භාවිතා කළ හැකියtypename std::add_const<T>::type


මා දන්නා
තරමින්, නම්

5
@someonewithpc මම කිසිවක් එකතු කළේ නැත, එය දැනටමත් පවතී, මම යතුරු ලියනය භාවිතා කිරීමේ උදාහරණයක් පෙන්වමින් සිටියෙමි. කරුණාකර en.cppreference.com/w/cpp/types/add_cv
Validus Oculus

10

මම පෝස්ටරයේ මුල් පිටපත විශාල පිළිතුරක් ඇති කියලා, නමුත් මම සිට වැදගත් සටහනක් තියෙනවා ඇති මෙන් මේ නූල් මත වැටීමට ඕනෑම කෙනෙකුට සඳහා යෝජනාව මම හිතන්නේ බව නම් විශේෂයෙන් ගැන අදහස් කනස්සල්ල, මෙහි සාකච්ඡාවට වටිනාකමින් දෙයක් එකතු typedefමූල පදය වේ අනාගතයේදී අවලංගු කරන ලද ලෙස සලකුණු කිරීමට හෝ අතිරික්ත / පැරණි බවට ඉවත් කිරීමට යන්නේ:

අච්චු අන්වර්ථයන් හඳුන්වාදීම සඳහා යතුරු ලියනය යතුරු ලියනය කරන්න (නැවත) භාවිතා කිරීමට යෝජනා කර ඇත:

template<class T>
  typedef std::vector<T, MyAllocator<T> > Vec;

අන්වර්ථ නාමයක් හඳුන්වා දීම සඳහා දැනටමත් දන්නා යතුරු පදයක් භාවිතා කිරීමේ වාසිය එම අංකනයට ඇත. කෙසේ වෙතත්, එය අවාසි කිහිපයක් ද පෙන්වයි [sic] ඒ අතර අන්වර්ථයක් වර්ගයක් නොව අච්චුවක් නම් නොකරන සන්දර්භයක් තුළ වර්ග නාමයක් සඳහා අන්වර්ථයක් හඳුන්වා දීමට දන්නා යතුරු පදයක් භාවිතා කිරීමේ ව්‍යාකූලත්වය; Vecවර්ගයක් සඳහා අන්වර්ථයක් නොවන අතර එය යතුරු ලියනයක නමක් සඳහා නොගත යුතුය. නම Vecපවුලේ නමකි std::vector<•, MyAllocator<•> >- වෙඩි උණ්ඩය ටයිප්-නමක් සඳහා ස්ථාන දරන්නෙකු වේ. එහි ප්‍රති we ලයක් ලෙස අපි “ටයිප්ඩෙෆ්” වාක්‍ය ඛණ්ඩය යෝජනා නොකරමු. අනෙක් අතට වාක්‍යය

template<class T>
  using Vec = std::vector<T, MyAllocator<T> >;

මෙතැන් සිටVec<T>std::vector<T, MyAllocator<T> > කියවීමට / අර්ථ දැක්වීමට හැකිය: මෙතැන් සිට, මම මේ සඳහා සමාන පදයක් ලෙස භාවිතා කරමි . එම කියවීමත් සමඟ අන්වර්ථකරණය සඳහා වන නව වාක්‍ය ඛණ්ඩය තර්කානුකූලව පෙනේ.

මට නම්, මෙයින් ගම්‍ය වන්නේ typedefC ++ හි මූලික පදය සඳහා අඛණ්ඩ සහය ලබා දෙන බැවින් එයට කේතය වඩාත් කියවිය හැකි සහ තේරුම් ගත හැකි වන බැවිනි.

යතුරුපදය යාවත්කාලීන කිරීම usingවිශේෂයෙන් සැකිලි සඳහා වූ අතර, (පිළිගත් පිළිතුරෙහි පෙන්වා ඇති පරිදි) ඔබ සැකිලි නොවන අය සමඟ වැඩ කරන විට usingසහ typedefයාන්ත්‍රිකව සමාන වන විට, තේරීම මුළුමනින්ම ක්‍රමලේඛකයාට පැවරෙන්නේ කියවීමේ හැකියාව සහ අභිප්‍රාය සන්නිවේදනය පදනම් කරගෙන ය. .


2

මූල පද දෙකම සමාන ය, නමුත් අවවාද කිහිපයක් තිබේ. එකක් නම් ශ්‍රිත දර්ශකයක් සමඟ ප්‍රකාශ using T = int (*)(int, int);කිරීම වඩා පැහැදිලි ය typedef int (*T)(int, int);. දෙවනුව, අච්චු අන්වර්ථ ආකෘතිය සමඟ කළ නොහැකි ය typedef. තෙවනුව, සී ඒපීඅයි නිරාවරණය කිරීම typedefපොදු ශීර්ෂයන්හි අවශ්‍ය වේ .

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.