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;
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.
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 keywordint
?– Some programmer dude
Sep 3 at 9:08