How do we print out the value_type of a C++ STL container?

How do we print out the value_type of a C++ STL container?



I know that STL containers have a value_type parameter and I've seen how it can be used to declare a type of a variable like:


value_type


vector<int>::value_type foo;



But can we just print this value_type to a console?


value_type



I want to see "string" in this example:


int main()
vector<string> v = "apple", "facebook", "microsoft", "google";
cout << v << endl;
cout << v.value_type << endl;
return 0;





The symbol value_type is not a member variable, it's a scoped type-name. Would you expect to be able to print the value of the keyword int?
– Some programmer dude
Sep 3 at 9:08



value_type


int





it's just a type, so you want to get type name as string?
– apple apple
Sep 3 at 9:08





Quite possible, but you'll need to add some code.
– bipll
Sep 3 at 9:09





That would be equivalent to cout << string;, which is not the same as cout << "string";.
– molbdnilo
Sep 3 at 9:14



cout << string;


cout << "string";





yeah @molbdnilo I want a type as human readable string
– Niakrais
Sep 3 at 9:26




5 Answers
5



X::value_type is no different from any other type alias (aka typedef) in this regard — C++ has no native way of converting a type to its source code string representation (not the least because that could be ambiguous). What you can do is use std::type_info::name:


X::value_type


std::type_info::name


cout << typeid(decltype(v)::value_type).name() << endl;



The resulting text is compiler dependent (and not even guaranteed to be easily human readable). It will be consistent within the same build of a program, but you cannot expect it to be the same across different compilers. In other words, it's useful for debugging, but cannot reliably be used in a persistent fashion.





Thank you, on my machine it gives me NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
– Niakrais
Sep 3 at 9:24



NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE





@You can use __cxa_demangle to get a readable type name: stackoverflow.com/a/23266701/1968
– Konrad Rudolph
Sep 3 at 9:26



__cxa_demangle





Isn't it only for gcc?
– Niakrais
Sep 3 at 9:30





@Niakrais: Not quite, it's for all compilers/platforms combinations using the Itanium ABI. The Itanium ABI is used on all Linux/MacOS platforms by all mainstream C++ compilers; the only widespread platform not using it is Windows, and thus MSVC and Clang in MSVC-compatible mode will not use it. Even on Windows, using Cygwin or MinGW means using the Itanium ABI.
– Matthieu M.
Sep 3 at 11:14



In addition to the typeid-based answer, I see one further possibility using Boost like this:


typeid


#include <boost/type_index.hpp>

cout << boost::typeindex::type_id_with_cvr<decltype(v)::value_type>().pretty_name() << "n";



The advantage is a portable, human-readable name that includes const/volatile qualifications and is consistent across major compilers and systems. The output on my machine is


// when compiled with gcc:
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
// ... and with clang:
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >



Decide for yourself whether this output qualifies as "human-readable", but also compare it to the typeid(...).name() approach, which on my machine gives:


typeid(...).name()


NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE



It's probably safe to assume that you need this type info for debug purposes(?).
If it is, don't forget gdb's built in whatis and ptype commands:


whatis


ptype


$ cat main.cpp
#include <iostream>
#include <vector>
using namespace std;
int main()
vector<string> v = "apple", "facebook", "microsoft", "google" ;
cout << v[2] << endl;
// cout << v.value_type << endl;
return 0;

$ cat gdbCommands.txt
break main
run
next
next
whatis v
quit
$ g++ -ggdb -o main main.cpp
$ gdb -x gdbCommands.txt ./main
GNU gdb (Ubuntu 8.0.1-0ubuntu1) 8.0.1
// bla bla bla ...
type = std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >>



I had a rather similar question some time ago. The answer there shown a function able to translate a type into a human readable string:


template <typename T> std::string TypeName()
auto name = typeid(T()).name(); // function type, not a constructor call!
int status = 0;

std::unique_ptr<char, void(*)(void*)> res
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
;

std::string ret((status == 0) ? res.get() : name);
if (ret.substr(ret.size() - 3) == " ()") ret.resize(ret.size() - 3);
return ret;



Once you have this TypeName function you can achieve your goal:


TypeName


int main()
vector<string> v = "apple", "facebook", "microsoft", "google" ;
cout << v << endl;
cout << TypeName<v.value_type>() << endl;
return 0;



Which should output (GCC HEAD 9 201809):


std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >



If it's for debug purpose, then this solution would work without any dependencies:


#include <regex>

template <typename T>
struct TypeToNameT

static std::string getTypeFromName()
#ifdef _MSC_VER
std::regex re("<(.*)>::.*");
std::string templateType(__FUNCTION__);
#else
std::regex re(" = (.*);");
std::string templateType(__PRETTY_FUNCTION__);
#endif
std::smatch match;
try

if (std::regex_search(templateType, match, re) && match.size() > 1)
return match.str(1);

catch (std::regex_error& e)
// Syntax error in the regular expression

return "";

;
/** Get the templated type name. This does not depends on RTTI, but on the preprocessor, so it should be quite safe to use even on old compilers */
template <typename T>
std::string getTypeName() return TypeToNameT<T>::getTypeFromName();


int main()
std::vector<std::string> v = "apple", "facebook", "microsoft", "google" ;
std::cout << getTypeName<decltype(v)::value_type>() << std::endl; // Returns: "std::__cxx11::basic_string<char>"
return 0;



Unlike the typeid based answer, this use the preprocessor and as such is not subject to name mangling (so the name is... readable).


typeid



Please notice that you can't use v.value_type as a type directly, it's not part of the instance v but of the type of v: std::vector<std::string>


v.value_type


v


v


std::vector<std::string>



The regex part is because the std::string class is too dumb and you need such oddities for a simple search/split code. If you have a decent string class, you'll not need regex here for extracting the part that's after the "=" string and before the ";".


std::string





__FUNCTION__ prints just the function name, without any additional information. You want __FUNCSIG__.
– HolyBlackCat
Sep 3 at 16:25



__FUNCTION__


__FUNCSIG__





Just tried it here: rextester.com/FDZT51977 and it seems to work with FUNCTION. With FUNCSIG, the regex must be modified since the signature is more complex. In all cases, thanks, I did not know about FUNCSIG before.
– xryl669
Sep 3 at 16:30






Nevermind, you're right. __FUNCTION__ doesn't contain template parameters of the function itself, so when I used this trick before, I resorted to use __FUNCSIG__. But it missed me that it contains the template parameters of enclosing classes. That's a nice idea.
– HolyBlackCat
Sep 3 at 16:33



__FUNCTION__


__FUNCSIG__



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)