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

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
11
down vote

favorite
2












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;







share|improve this question






















  • 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










  • 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











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














up vote
11
down vote

favorite
2












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;







share|improve this question






















  • 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










  • 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











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












up vote
11
down vote

favorite
2









up vote
11
down vote

favorite
2






2





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;







share|improve this question














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;









share|improve this question













share|improve this question




share|improve this question








edited Sep 3 at 19:56









Peter Mortensen

12.9k1983111




12.9k1983111










asked Sep 3 at 9:06









Niakrais

14610




14610











  • 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










  • 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











  • 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











  • 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











  • 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












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.






share|improve this answer






















  • Thank you, on my machine it gives me NSt3__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

















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





share|improve this answer





























    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> >>





    share|improve this answer



























      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> >






      share|improve this answer



























        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 ";".






        share|improve this answer




















        • __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











        Your Answer





        StackExchange.ifUsing("editor", function ()
        StackExchange.using("externalEditor", function ()
        StackExchange.using("snippets", function ()
        StackExchange.snippets.init();
        );
        );
        , "code-snippets");

        StackExchange.ready(function()
        var channelOptions =
        tags: "".split(" "),
        id: "1"
        ;
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function()
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled)
        StackExchange.using("snippets", function()
        createEditor();
        );

        else
        createEditor();

        );

        function createEditor()
        StackExchange.prepareEditor(
        heartbeatType: 'answer',
        convertImagesToLinks: true,
        noModals: false,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        );



        );













         

        draft saved


        draft discarded


















        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






























        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.






        share|improve this answer






















        • Thank you, on my machine it gives me NSt3__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














        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.






        share|improve this answer






















        • Thank you, on my machine it gives me NSt3__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












        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.






        share|improve this answer














        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.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Sep 3 at 9:12

























        answered Sep 3 at 9:09









        Angew

        127k11236333




        127k11236333











        • Thank you, on my machine it gives me NSt3__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







        • 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












        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





        share|improve this answer


























          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





          share|improve this answer
























            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





            share|improve this answer














            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






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Sep 3 at 19:57









            Peter Mortensen

            12.9k1983111




            12.9k1983111










            answered Sep 3 at 9:12









            lubgr

            6,0701339




            6,0701339




















                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> >>





                share|improve this answer
























                  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> >>





                  share|improve this answer






















                    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> >>





                    share|improve this answer












                    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> >>






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Sep 3 at 10:13









                    OrenIshShalom

                    845520




                    845520




















                        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> >






                        share|improve this answer
























                          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> >






                          share|improve this answer






















                            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> >






                            share|improve this answer












                            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> >







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Sep 3 at 13:55









                            Paula_plus_plus

                            6,58442758




                            6,58442758




















                                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 ";".






                                share|improve this answer




















                                • __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















                                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 ";".






                                share|improve this answer




















                                • __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













                                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 ";".






                                share|improve this answer












                                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 ";".







                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                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

















                                • __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


















                                 

                                draft saved


                                draft discarded















































                                 


                                draft saved


                                draft discarded














                                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













































































                                Comments

                                Popular posts from this blog

                                Long meetings (6-7 hours a day): Being “babysat” by supervisor

                                Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

                                Confectionery