Figuring out the kind of a adaptable astatine runtime is a communal demand successful C++, particularly once dealing with analyzable methods oregon generic programming. Piece modular C++ doesn’t message a nonstop, azygous-relation attack similar any scripting languages, location are respective effectual strategies to accomplish this. Knowing these strategies empowers builders to compose much strong and adaptable codification. This article explores assorted approaches, from leveraging the typeid function to using precocious strategies similar compile-clip observation, enabling you to efficaciously find adaptable sorts successful your C++ tasks.
Utilizing the typeid
Function
The about simple attack for acquiring kind accusation throughout runtime is the typeid
function. This function, mixed with the std::type_info
people, supplies a mechanics to retrieve the kind accusation of a adaptable. The sanction()
methodology of the std::type_info
entity returns a C-kind drawstring cooperation of the kind’s sanction.
Nevertheless, the output from typeid.sanction()
tin change crossed compilers and whitethorn not ever beryllium person-affable. It frequently gives mangled names, particularly for analyzable sorts. Contempt this regulation, typeid
is utile for basal kind recognition and comparisons.
Illustration:
see <iostream> see <typeinfo> int chief() { int x = 10; treble y = three.14; std::cout << typeid(x).sanction() << std::endl; // Output mightiness beryllium "i" std::cout << typeid(y).sanction() << std::endl; // Output mightiness beryllium "d" instrument zero; }
Leveraging Compile-Clip Observation (C++23 and past)
C++23 introduces compile-clip observation options, offering much almighty instruments for kind introspection. Piece inactive nether improvement, observation volition change builders to retrieve kind accusation throughout compilation, beginning ahead potentialities for precocious static investigation and codification procreation.
This characteristic volition let builders to examine and manipulate the construction of sorts, together with associate variables and capabilities, astatine compile clip. This volition change much blase options for figuring out and using kind accusation inside the codification.
Support an oculus retired for the additional improvement and implementation of compile-clip observation successful C++23 and future requirements.
Enhance.TypeIndex Room
For a much strong and person-affable attack earlier C++23 observation turns into wide disposable, the Enhance.TypeIndex room is a large action. It builds upon typeid
and offers demangled kind names, making the output much readable and comprehensible.
Enhance.TypeIndex enhances kind recognition and affords functionalities past the modular typeid
, contributing to cleaner and much manageable codification once running with kind accusation.
Illustration:
see <increase/type_index.hpp> see <iostream> int chief() { int x = 5; std::cout << enhance::typeindex::type_id_with_cvr<decltype(x)>().pretty_name() << std::endl; instrument zero; }
Outer Libraries and Instruments
Past Increase.TypeIndex, another outer libraries and instruments supply much specialised functionalities for kind introspection and manipulation. These tin beryllium peculiarly utile successful debugging, serialization, and another eventualities wherever elaborate kind accusation is important. Exploring these sources tin additional widen your quality to activity with adaptable varieties successful C++.
1 illustration is the Enhance room which has galore almighty instruments for metaprogramming and running with varieties.
Different invaluable assets is cppreference.com, which gives blanket documentation connected modular C++ options, together with kind-associated functionalities.
typeid
is speedy and readily disposable, however its output tin beryllium hard to construe.- Increase.TypeIndex offers much quality-readable kind names.
- See the essential headers:
<typeinfo>
fortypeid
and<enhance/type_index.hpp>
for Enhance.TypeIndex. - Usage the
typeid
function oregon theenhance::typeindex::type_id_with_cvr<decltype(adaptable)>().pretty_name()
relation to retrieve the kind sanction. - Procedure oregon show the retrieved kind accusation.
Featured Snippet: Piece typeid
is readily disposable successful modular C++, its output tin beryllium cryptic. For much person-affable output, Increase.TypeIndex presents a handy resolution with its pretty_name()
relation.
Larn much astir C++ methods
FAQs
Q: Wherefore is typeid.sanction()
’s output typically mangled?
A: The mangling is owed to C++’s sanction ornament mechanics, which ensures alone relation and kind names throughout linking. Demangling libraries oregon instruments tin person these mangled names into readable codecs.
Knowing however to find adaptable varieties astatine runtime is important for penning versatile and adaptable C++ codification. By using the methods mentioned present, ranging from the basal typeid
function to the much precocious Increase.TypeIndex room and trying guardant to compile-clip observation, you tin equip your self with the instruments essential to grip kind introspection efficaciously successful your tasks. Arsenic C++ continues to germinate, staying knowledgeable astir fresh options and libraries volition additional heighten your quality to navigate and negociate kind accusation successful your codification. Research the linked sources for additional particulars and research however these methods tin beryllium built-in into your improvement workflow. Stack Overflow tin besides beryllium an invaluable assets for uncovering circumstantial options and studying from another builders’ experiences. Eventually, the authoritative ISO C++ web site supplies authoritative accusation connected the C++ modular.
Question & Answer :
For illustration:
int a = 12; cout << typeof(a) << endl;
Anticipated output:
int
C++eleven replace to a precise aged motion: Mark adaptable kind successful C++.
The accepted (and bully) reply is to usage typeid(a).sanction()
, wherever a
is a adaptable sanction.
Present successful C++eleven we person decltype(x)
, which tin bend an look into a kind. And decltype()
comes with its ain fit of precise absorbing guidelines. For illustration decltype(a)
and decltype((a))
volition mostly beryllium antithetic varieties (and for bully and comprehensible causes erstwhile these causes are uncovered).
Volition our trusty typeid(a).sanction()
aid america research this courageous fresh planet?
Nary.
However the implement that volition is not that complex. And it is that implement which I americium utilizing arsenic an reply to this motion. I volition comparison and opposition this fresh implement to typeid(a).sanction()
. And this fresh implement is really constructed connected apical of typeid(a).sanction()
.
The cardinal content:
typeid(a).sanction()
throws distant cv-qualifiers, references, and lvalue/rvalue-ness. For illustration:
const int ci = zero; std::cout << typeid(ci).sanction() << '\n';
For maine outputs:
i
and I’m guessing connected MSVC outputs:
int
I.e. the const
is gone. This is not a QOI (Choice Of Implementation) content. The modular mandates this behaviour.
What I’m recommending beneath is:
template <typename T> std::drawstring type_name();
which would beryllium utilized similar this:
const int ci = zero; std::cout << type_name<decltype(ci)>() << '\n';
and for maine outputs:
int const
<disclaimer>
I person not examined this connected MSVC. </disclaimer>
However I invited suggestions from these who bash.
The C++eleven Resolution
I americium utilizing __cxa_demangle
for non-MSVC platforms arsenic urge by ipapadop successful his reply to demangle varieties. However connected MSVC I’m trusting typeid
to demangle names (untested). And this center is wrapped about any elemental investigating that detects, restores and experiences cv-qualifiers and references to the enter kind.
#see <type_traits> #see <typeinfo> #ifndef _MSC_VER # see <cxxabi.h> #endif #see <representation> #see <drawstring> #see <cstdlib> template <people T> std::drawstring type_name() { typedef typename std::remove_reference<T>::kind TR; std::unique_ptr<char, void(*)(void*)> ain ( #ifndef _MSC_VER abi::__cxa_demangle(typeid(TR).sanction(), nullptr, nullptr, nullptr), #other nullptr, #endif std::escaped ); std::drawstring r = ain != nullptr ? ain.acquire() : typeid(TR).sanction(); if (std::is_const<TR>::worth) r += " const"; if (std::is_volatile<TR>::worth) r += " unstable"; if (std::is_lvalue_reference<T>::worth) r += "&"; other if (std::is_rvalue_reference<T>::worth) r += "&&"; instrument r; }
The Outcomes
With this resolution I tin bash this:
int& foo_lref(); int&& foo_rref(); int foo_value(); int chief() { int i = zero; const int ci = zero; std::cout << "decltype(i) is " << type_name<decltype(i)>() << '\n'; std::cout << "decltype((i)) is " << type_name<decltype((i))>() << '\n'; std::cout << "decltype(ci) is " << type_name<decltype(ci)>() << '\n'; std::cout << "decltype((ci)) is " << type_name<decltype((ci))>() << '\n'; std::cout << "decltype(static_cast<int&>(i)) is " << type_name<decltype(static_cast<int&>(i))>() << '\n'; std::cout << "decltype(static_cast<int&&>(i)) is " << type_name<decltype(static_cast<int&&>(i))>() << '\n'; std::cout << "decltype(static_cast<int>(i)) is " << type_name<decltype(static_cast<int>(i))>() << '\n'; std::cout << "decltype(foo_lref()) is " << type_name<decltype(foo_lref())>() << '\n'; std::cout << "decltype(foo_rref()) is " << type_name<decltype(foo_rref())>() << '\n'; std::cout << "decltype(foo_value()) is " << type_name<decltype(foo_value())>() << '\n'; }
and the output is:
decltype(i) is int decltype((i)) is int& decltype(ci) is int const decltype((ci)) is int const& decltype(static_cast<int&>(i)) is int& decltype(static_cast<int&&>(i)) is int&& decltype(static_cast<int>(i)) is int decltype(foo_lref()) is int& decltype(foo_rref()) is int&& decltype(foo_value()) is int
Line (for illustration) the quality betwixt decltype(i)
and decltype((i))
. The erstwhile is the kind of the declaration of i
. The second is the “kind” of the look i
. (expressions ne\’er person mention kind, however arsenic a normal decltype
represents lvalue expressions with lvalue references).
Frankincense this implement is an fantabulous conveyance conscionable to larn astir decltype
, successful summation to exploring and debugging your ain codification.
Successful opposition, if I had been to physique this conscionable connected typeid(a).sanction()
, with out including backmost mislaid cv-qualifiers oregon references, the output would beryllium:
decltype(i) is int decltype((i)) is int decltype(ci) is int decltype((ci)) is int decltype(static_cast<int&>(i)) is int decltype(static_cast<int&&>(i)) is int decltype(static_cast<int>(i)) is int decltype(foo_lref()) is int decltype(foo_rref()) is int decltype(foo_value()) is int
I.e. All mention and cv-qualifier is stripped disconnected.
C++14 Replace
Conscionable once you deliberation you’ve bought a resolution to a job nailed, person ever comes retired of obscurity and exhibits you a overmuch amended manner. :-)
This reply from Jamboree reveals however to acquire the kind sanction successful C++14 astatine compile clip. It is a superb resolution for a mates causes:
- It’s astatine compile clip!
- You acquire the compiler itself to bash the occupation alternatively of a room (equal a std::lib). This means much close outcomes for the newest communication options (similar lambdas).
Jamboree’s reply doesn’t rather laic every thing retired for VS, and I’m tweaking his codification a small spot. However since this reply will get a batch of views, return any clip to spell complete location and upvote his reply, with out which, this replace would ne\’er person occurred.
#see <cstddef> #see <stdexcept> #see <cstring> #see <ostream> #ifndef _MSC_VER # if __cplusplus < 201103 # specify CONSTEXPR11_TN # specify CONSTEXPR14_TN # specify NOEXCEPT_TN # elif __cplusplus < 201402 # specify CONSTEXPR11_TN constexpr # specify CONSTEXPR14_TN # specify NOEXCEPT_TN noexcept # other # specify CONSTEXPR11_TN constexpr # specify CONSTEXPR14_TN constexpr # specify NOEXCEPT_TN noexcept # endif #other // _MSC_VER # if _MSC_VER < 1900 # specify CONSTEXPR11_TN # specify CONSTEXPR14_TN # specify NOEXCEPT_TN # elif _MSC_VER < 2000 # specify CONSTEXPR11_TN constexpr # specify CONSTEXPR14_TN # specify NOEXCEPT_TN noexcept # other # specify CONSTEXPR11_TN constexpr # specify CONSTEXPR14_TN constexpr # specify NOEXCEPT_TN noexcept # endif #endif // _MSC_VER people static_string { const char* const p_; const std::size_t sz_; national: typedef const char* const_iterator; template <std::size_t N> CONSTEXPR11_TN static_string(const char(&a)[N]) NOEXCEPT_TN : p_(a) , sz_(N-1) {} CONSTEXPR11_TN static_string(const char* p, std::size_t N) NOEXCEPT_TN : p_(p) , sz_(N) {} CONSTEXPR11_TN const char* information() const NOEXCEPT_TN {instrument p_;} CONSTEXPR11_TN std::size_t dimension() const NOEXCEPT_TN {instrument sz_;} CONSTEXPR11_TN const_iterator statesman() const NOEXCEPT_TN {instrument p_;} CONSTEXPR11_TN const_iterator extremity() const NOEXCEPT_TN {instrument p_ + sz_;} CONSTEXPR11_TN char function[](std::size_t n) const { instrument n < sz_ ? p_[n] : propulsion std::out_of_range("static_string"); } }; inline std::ostream& function<<(std::ostream& os, static_string const& s) { instrument os.compose(s.information(), s.measurement()); } template <people T> CONSTEXPR14_TN static_string type_name() { #ifdef __clang__ static_string p = __PRETTY_FUNCTION__; instrument static_string(p.information() + 31, p.dimension() - 31 - 1); #elif outlined(__GNUC__) static_string p = __PRETTY_FUNCTION__; # if __cplusplus < 201402 instrument static_string(p.information() + 36, p.measurement() - 36 - 1); # other instrument static_string(p.information() + forty six, p.measurement() - forty six - 1); # endif #elif outlined(_MSC_VER) static_string p = __FUNCSIG__; instrument static_string(p.information() + 38, p.measurement() - 38 - 7); #endif }
This codification volition car-backoff connected the constexpr
if you’re inactive caught successful past C++eleven. And if you’re coating connected the cave partition with C++ninety eight/03, the noexcept
is sacrificed arsenic fine.
C++17 Replace
Successful the feedback beneath Lyberta factors retired that the fresh std::string_view
tin regenerate static_string
:
template <people T> constexpr std::string_view type_name() { utilizing namespace std; #ifdef __clang__ string_view p = __PRETTY_FUNCTION__; instrument string_view(p.information() + 34, p.measurement() - 34 - 1); #elif outlined(__GNUC__) string_view p = __PRETTY_FUNCTION__; # if __cplusplus < 201402 instrument string_view(p.information() + 36, p.dimension() - 36 - 1); # other instrument string_view(p.information() + forty nine, p.discovery(';', forty nine) - forty nine); # endif #elif outlined(_MSC_VER) string_view p = __FUNCSIG__; instrument string_view(p.information() + eighty four, p.dimension() - eighty four - 7); #endif }
I’ve up to date the constants for VS acknowledgment to the precise good detective activity by Jive Dadson successful the feedback beneath.
Replace:
Beryllium certain to cheque retired this rewrite oregon this rewrite beneath which destroy the unreadable magic numbers successful my newest formulation.