How do we print out the value_type of a C++ STL container?
Clash Royale CLAN TAG#URR8PPP
up vote
11
down vote
favorite
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:
vector<int>::value_type foo;
But can we just print this value_type
to a console?
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;
c++ stl
 |Â
show 1 more comment
up vote
11
down vote
favorite
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:
vector<int>::value_type foo;
But can we just print this value_type
to a console?
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;
c++ stl
The symbolvalue_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
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 tocout << string;
, which is not the same ascout << "string";
.
â molbdnilo
Sep 3 at 9:14
yeah @molbdnilo I want a type as human readable string
â Niakrais
Sep 3 at 9:26
 |Â
show 1 more comment
up vote
11
down vote
favorite
up vote
11
down vote
favorite
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:
vector<int>::value_type foo;
But can we just print this value_type
to a console?
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;
c++ stl
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:
vector<int>::value_type foo;
But can we just print this value_type
to a console?
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;
c++ stl
edited Sep 3 at 19:56
Peter Mortensen
12.9k1983111
12.9k1983111
asked Sep 3 at 9:06
Niakrais
14610
14610
The symbolvalue_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
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 tocout << string;
, which is not the same ascout << "string";
.
â molbdnilo
Sep 3 at 9:14
yeah @molbdnilo I want a type as human readable string
â Niakrais
Sep 3 at 9:26
 |Â
show 1 more comment
The symbolvalue_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
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 tocout << string;
, which is not the same ascout << "string";
.
â molbdnilo
Sep 3 at 9:14
yeah @molbdnilo I want a type as human readable string
â Niakrais
Sep 3 at 9:26
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
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
it's just a type, so you want to get type name as string?
â apple apple
Sep 3 at 9:08
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
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
That would be equivalent to
cout << string;
, which is not the same as cout << "string";
.â molbdnilo
Sep 3 at 9:14
yeah @molbdnilo I want a type as human readable string
â Niakrais
Sep 3 at 9:26
yeah @molbdnilo I want a type as human readable string
â Niakrais
Sep 3 at 9:26
 |Â
show 1 more comment
5 Answers
5
active
oldest
votes
up vote
12
down vote
accepted
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
:
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 meNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
â Niakrais
Sep 3 at 9:24
1
@You can use__cxa_demangle
to get a readable type name: stackoverflow.com/a/23266701/1968
â Konrad Rudolph
Sep 3 at 9:26
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
add a comment |Â
up vote
5
down vote
In addition to the typeid
-based answer, I see one further possibility using Boost like this:
#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:
NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
add a comment |Â
up vote
1
down vote
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:
$ 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> >>
add a comment |Â
up vote
1
down vote
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:
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> >
add a comment |Â
up vote
1
down vote
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).
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>
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 ";".
__FUNCTION__
prints just the function name, without any additional information. You want__FUNCSIG__
.
â HolyBlackCat
Sep 3 at 16:25
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
add a comment |Â
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
12
down vote
accepted
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
:
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 meNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
â Niakrais
Sep 3 at 9:24
1
@You can use__cxa_demangle
to get a readable type name: stackoverflow.com/a/23266701/1968
â Konrad Rudolph
Sep 3 at 9:26
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
add a comment |Â
up vote
12
down vote
accepted
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
:
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 meNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
â Niakrais
Sep 3 at 9:24
1
@You can use__cxa_demangle
to get a readable type name: stackoverflow.com/a/23266701/1968
â Konrad Rudolph
Sep 3 at 9:26
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
add a comment |Â
up vote
12
down vote
accepted
up vote
12
down vote
accepted
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
:
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.
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
:
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.
edited Sep 3 at 9:12
answered Sep 3 at 9:09
Angew
127k11236333
127k11236333
Thank you, on my machine it gives meNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
â Niakrais
Sep 3 at 9:24
1
@You can use__cxa_demangle
to get a readable type name: stackoverflow.com/a/23266701/1968
â Konrad Rudolph
Sep 3 at 9:26
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
add a comment |Â
Thank you, on my machine it gives meNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
â Niakrais
Sep 3 at 9:24
1
@You can use__cxa_demangle
to get a readable type name: stackoverflow.com/a/23266701/1968
â Konrad Rudolph
Sep 3 at 9:26
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
Thank you, on my machine it gives me
NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
â Niakrais
Sep 3 at 9:24
Thank you, on my machine it gives me
NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
â Niakrais
Sep 3 at 9:24
1
1
@You can use
__cxa_demangle
to get a readable type name: stackoverflow.com/a/23266701/1968â Konrad Rudolph
Sep 3 at 9:26
@You can use
__cxa_demangle
to get a readable type name: stackoverflow.com/a/23266701/1968â Konrad Rudolph
Sep 3 at 9:26
Isn't it only for gcc?
â Niakrais
Sep 3 at 9:30
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
@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
add a comment |Â
up vote
5
down vote
In addition to the typeid
-based answer, I see one further possibility using Boost like this:
#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:
NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
add a comment |Â
up vote
5
down vote
In addition to the typeid
-based answer, I see one further possibility using Boost like this:
#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:
NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
add a comment |Â
up vote
5
down vote
up vote
5
down vote
In addition to the typeid
-based answer, I see one further possibility using Boost like this:
#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:
NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
In addition to the typeid
-based answer, I see one further possibility using Boost like this:
#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:
NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
edited Sep 3 at 19:57
Peter Mortensen
12.9k1983111
12.9k1983111
answered Sep 3 at 9:12
lubgr
6,0701339
6,0701339
add a comment |Â
add a comment |Â
up vote
1
down vote
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:
$ 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> >>
add a comment |Â
up vote
1
down vote
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:
$ 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> >>
add a comment |Â
up vote
1
down vote
up vote
1
down vote
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:
$ 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> >>
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:
$ 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> >>
answered Sep 3 at 10:13
OrenIshShalom
845520
845520
add a comment |Â
add a comment |Â
up vote
1
down vote
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:
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> >
add a comment |Â
up vote
1
down vote
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:
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> >
add a comment |Â
up vote
1
down vote
up vote
1
down vote
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:
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> >
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:
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> >
answered Sep 3 at 13:55
Paula_plus_plus
6,58442758
6,58442758
add a comment |Â
add a comment |Â
up vote
1
down vote
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).
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>
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 ";".
__FUNCTION__
prints just the function name, without any additional information. You want__FUNCSIG__
.
â HolyBlackCat
Sep 3 at 16:25
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
add a comment |Â
up vote
1
down vote
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).
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>
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 ";".
__FUNCTION__
prints just the function name, without any additional information. You want__FUNCSIG__
.
â HolyBlackCat
Sep 3 at 16:25
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
add a comment |Â
up vote
1
down vote
up vote
1
down vote
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).
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>
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 ";".
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).
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>
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 ";".
answered Sep 3 at 14:14
xryl669
1,4301327
1,4301327
__FUNCTION__
prints just the function name, without any additional information. You want__FUNCSIG__
.
â HolyBlackCat
Sep 3 at 16:25
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
add a comment |Â
__FUNCTION__
prints just the function name, without any additional information. You want__FUNCSIG__
.
â HolyBlackCat
Sep 3 at 16:25
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__
prints just the function name, without any additional information. You want __FUNCSIG__
.â HolyBlackCat
Sep 3 at 16:25
__FUNCTION__
prints just the function name, without any additional information. You want __FUNCSIG__
.â HolyBlackCat
Sep 3 at 16:25
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
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
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
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52146507%2fhow-do-we-print-out-the-value-type-of-a-c-stl-container%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 ascout << "string";
.â molbdnilo
Sep 3 at 9:14
yeah @molbdnilo I want a type as human readable string
â Niakrais
Sep 3 at 9:26