Is it possible to print a variable's type in standard C++?

前端 未结 21 1661
南笙
南笙 2020-11-22 01:41

For example:

int a = 12;
cout << typeof(a) << endl;

Expected output:

int
相关标签:
21条回答
  • 2020-11-22 02:30

    According to Howard's solution, if you don't like the magic number, I think this is a good way to represent and it looks intuitive:

    #include <string_view>
    
    template <typename T>
    constexpr auto type_name() noexcept {
      std::string_view name = "Error: unsupported compiler", prefix, suffix;
    #ifdef __clang__
      name = __PRETTY_FUNCTION__;
      prefix = "auto type_name() [T = ";
      suffix = "]";
    #elif defined(__GNUC__)
      name = __PRETTY_FUNCTION__;
      prefix = "constexpr auto type_name() [with T = ";
      suffix = "]";
    #elif defined(_MSC_VER)
      name = __FUNCSIG__;
      prefix = "auto __cdecl type_name<";
      suffix = ">(void) noexcept";
    #endif
      name.remove_prefix(prefix.size());
      name.remove_suffix(suffix.size());
      return name;
    }
    

    Demo.

    0 讨论(0)
  • 2020-11-22 02:30

    For anyone still visiting, I've recently had the same issue and decided to write a small library based on answers from this post. It provides constexpr type names and type indices und is is tested on Mac, Windows and Ubuntu.

    The library code is here: https://github.com/TheLartians/StaticTypeInfo

    0 讨论(0)
  • 2020-11-22 02:31

    Howard Hinnant used magic numbers to extract type name. 康桓瑋 suggested string prefix and suffix. But prefix/suffix keep changing. With “probe_type” type_name automatically calculates prefix and suffix sizes for “probe_type” to extract type name:

    #include <string_view>
    using namespace std;
    
    namespace typeName {
     template <typename T>
      constexpr string_view wrapped_type_name () {
    #ifdef __clang__
        return __PRETTY_FUNCTION__;
    #elif defined(__GNUC__)
        return  __PRETTY_FUNCTION__;
    #elif defined(_MSC_VER)
        return  __FUNCSIG__;
    #endif
      }
    
      class probe_type;
      constexpr string_view probe_type_name ("typeName::probe_type");
      constexpr string_view probe_type_name_elaborated ("class typeName::probe_type");
      constexpr string_view probe_type_name_used (wrapped_type_name<probe_type> ().find (probe_type_name_elaborated) != -1 ? probe_type_name_elaborated : probe_type_name);
    
      constexpr size_t prefix_size () {
        return wrapped_type_name<probe_type> ().find (probe_type_name_used);
      }
    
      constexpr size_t suffix_size () {
        return wrapped_type_name<probe_type> ().length () - prefix_size () - probe_type_name_used.length ();
      }
    
      template <typename T>
      string_view type_name () {
        constexpr auto type_name = wrapped_type_name<T> ();
    
        return type_name.substr (prefix_size (), type_name.length () - prefix_size () - suffix_size ());
      }
    }
    
    #include <iostream>
    
    using typeName::type_name;
    using typeName::probe_type;
    
    class test;
    
    int main () {
      cout << type_name<class test> () << endl;
    
      cout << type_name<const int*&> () << endl;
      cout << type_name<unsigned int> () << endl;
    
      const int ic = 42;
      const int* pic = &ic;
      const int*& rpic = pic;
      cout << type_name<decltype(ic)> () << endl;
      cout << type_name<decltype(pic)> () << endl;
      cout << type_name<decltype(rpic)> () << endl;
    
      cout << type_name<probe_type> () << endl;
    }
    

    Output

    gcc 10.2:

    test
    const int *&
    unsigned int
    const int
    const int *
    const int *&
    typeName::probe_type
    

    clang 11.0.0:

    test
    const int *&
    unsigned int
    const int
    const int *
    const int *&
    typeName::probe_type
    

    VS 2019 version 16.7.6:

    class test
    const int*&
    unsigned int
    const int
    const int*
    const int*&
    class typeName::probe_type
    
    0 讨论(0)
提交回复
热议问题