C++ boost::typeindex::type_id()。pretty_name()不是“pretty”

C++ boost::typeindex::type_id()。pretty_name()不是“pretty”,c++,boost,rtti,typeinfo,C++,Boost,Rtti,Typeinfo,我试图在标准输出上打印一些变量的类型。此代码: std::string mystr {"dsadsadas"}; std::cout << boost::typeindex::type_id< decltype(mystr) >().pretty_name() << std::endl; 结果: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1:: allo

我试图在标准输出上打印一些变量的类型。此代码:

std::string mystr {"dsadsadas"};
std::cout << boost::typeindex::type_id< decltype(mystr) >().pretty_name() << std::endl;
结果:

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

这绝对不漂亮。。为什么会这样?有什么解决办法吗??注意:我是使用c++14语义使用clang++编译的

我有一个名为cpputil的库,它在bitbucket上私自维护,它有许多适用于c++11或更好的快捷方式

其中一个概念是cpputil::classname_of x

其思想是,如果一个类有一个名为classname的静态成员数据或函数,则该数据或函数用于打印该类的名称。如果没有,您可以提供一个提供类名的免费函数。否则,typeid.name将用作回退

现在你的类名可以像你喜欢的那样漂亮


我在bitbucket上私人维护了一个名为cpputil的库,它有许多适用于c++11或更高版本的有用快捷方式

其中一个概念是cpputil::classname_of x

其思想是,如果一个类有一个名为classname的静态成员数据或函数,则该数据或函数用于打印该类的名称。如果没有,您可以提供一个提供类名的免费函数。否则,typeid.name将用作回退

现在你的类名可以像你喜欢的那样漂亮


我怀疑您显示的输出是否来自您显示的代码,因为代码是一个简单的std::string,而不是std::multimap。除此之外,它是一个漂亮的名字,否则你会得到一个不漂亮的名字。对不起,我粘贴了错误的代码片段-我刚刚用正确的输出更新了答案。那么,不知何故,难道就没有办法达到std::sting吗?@MarinosK“不漂亮”是什么意思?这实际上是类型定义std::string的结果,您是否希望看到损坏的名称?您希望看到什么,std::string?根据标准,这是一个别名。好的,知道了-std::string是一个漂亮的名字。。谢谢。我怀疑您显示的输出是否来自您显示的代码,因为代码是简单的std::string,而不是std::multimap。除此之外,它是一个漂亮的名字,否则你会得到一个不漂亮的名字。对不起,我粘贴了错误的代码片段-我刚刚用正确的输出更新了答案。那么,不知何故,难道就没有办法达到std::sting吗?@MarinosK“不漂亮”是什么意思?这实际上是类型定义std::string的结果,您是否希望看到损坏的名称?您希望看到什么,std::string?根据标准,这是一个别名。好的,知道了-std::string是一个漂亮的名字。。谢谢。它不适用于像boost pretty_name这样的模板。是的,因为我写了这篇文章,我发现boost有一个使用cxxabi库的工具。boost解决方案的唯一问题是,它使用运行时代码来构建漂亮的名称,而上面的一个则是常数折叠的。它不适用于像boost pretty_name这样的模板。是的,因为我写了这篇文章,我发现boost有一个使用cxxabi库的工具。boost解决方案的唯一问题是,它使用运行时代码来构建漂亮的名称,而上面的一个则是常数折叠的。YMMV。
#include <iostream>
#include <type_traits>

/// static member of any type
namespace cpputil {
namespace detail {
    template<class T>
    constexpr auto has_static_member_classname(...)
    -> std::false_type
    {
        return {};
    }

    template<class T>
    constexpr auto has_static_member_classname(int)
    -> decltype(T::classname, void(), std::true_type())
    {
        return {};
    }

    // static member of type function that returns anything but takes no args

    template<class T>
    constexpr auto has_static_function_classname(...)
    -> std::false_type
    { return {}; }

    template<class T>
    constexpr auto has_static_function_classname(int)
    -> decltype(T::classname(), void(), std::true_type())
    { return {}; }
}
// templated free function that takes no args, used as a fallback but may be overriden

template<class T> decltype(auto) classname() { return typeid(T).name(); }

namespace detail {
    template<class T>
    constexpr auto has_free_function_classname_0(...)
    -> std::false_type
    { return {}; }

    template<class T>
    constexpr auto has_free_function_classname_0(int)
    -> decltype(classname<T>(), void(), std::true_type())
    { return {}; }

    // free function that takes a const ref

    template<class T>
    constexpr auto has_free_function_classname_1(...)
    -> std::false_type
    { return {}; }

    template<class T>
    constexpr auto has_free_function_classname_1(int)
    -> decltype(classname(std::declval<T>()), void(), std::true_type())
    { return {}; }


    template<class T, typename = void>
    struct classname_finder;

        // highest priority - if there is a free function taking 1 parameter findable by ADL - use this
        template<class T>
        struct classname_finder<
        T,
        std::enable_if_t<
        decltype(has_free_function_classname_1<T>(0))::value
        >
        >
        {
            static constexpr decltype(auto) apply() { return classname(*reinterpret_cast<const T*>(0)); }
            static constexpr decltype(auto) apply(const T& t) { return classname(t); }
        };


        // priority 2 - if there is a static function, use that
        template<class T>
        struct classname_finder<
        T,
        std::enable_if_t<
        decltype(has_static_function_classname<T>(0))::value &&
        !decltype(has_free_function_classname_1<T>(0))::value
        >
        >
        {
            static constexpr decltype(auto) apply() { return T::classname(); }
            static constexpr decltype(auto) apply(const T&) { return T::classname(); }
        };

        // priority 3 - if there is a static data member, use that
    template<class T>
    struct classname_finder<
        T,
        std::enable_if_t<
            decltype(has_static_member_classname<T>(0))::value &&
            !decltype(has_static_function_classname<T>(0))::value &&
            !decltype(has_free_function_classname_1<T>(0))::value
        >
    >
    {
        static constexpr decltype(auto) apply() { return T::classname; }
        static constexpr decltype(auto) apply(const T&) { return T::classname; }
    };

        // finally, use the cpputil::classname_of<X>() template overload
    template<class T>
    struct classname_finder<
        T,
        std::enable_if_t<
            !decltype(has_static_member_classname<T>(0))::value &&
            !decltype(has_static_function_classname<T>(0))::value &&
            !decltype(has_free_function_classname_1<T>(0))::value &&
            decltype(has_free_function_classname_0<T>(0))::value
        >
    >
    {
        static constexpr decltype(auto) apply() { return classname<T>(); }
        static constexpr decltype(auto) apply(const T&) { return classname<T>(); }
    };
}


template<class T>
auto classname_of(const T& t)
{
    return detail::classname_finder<T>::apply(t);
}

template<class T>
auto classname_of()
{
    return detail::classname_finder<T>::apply();
}
}

struct class_a
{
    static const char* classname() { return "class_a"; }
};

struct class_b
{
    constexpr static const char* classname = "class_b";
};

struct class_c
{
};
namespace cpputil {
    template<> decltype(auto) classname<class_c>() { return "class_c"; }
}

struct class_d
{
};

decltype(auto) classname(const class_d&) { return "class_d"; }

struct class_e {
    static const std::string& classname() { static const std::string _("class_e static function"); return _; }
};
static const char* classname(const class_e&) {
    return "class_e free function should take priority";
}

// no classname decoration. should fall back to typeid() solution
struct class_f {

};

using namespace std;

auto main() -> int
{
    class_a a;
    class_b b;
    class_c c;
    class_d d;
    class_e e;
    class_f f;
    cout << cpputil::classname_of(a) << endl;
    cout << cpputil::classname_of(b) << endl;
    cout << cpputil::classname_of(c) << endl;
    cout << cpputil::classname_of(d) << endl;
    cout << cpputil::classname_of(e) << endl;
    cout << cpputil::classname_of(f) << endl;
    cout << endl;

    cout << cpputil::classname_of<class_a>() << endl;
    cout << cpputil::classname_of<class_b>() << endl;
    cout << cpputil::classname_of<class_c>() << endl;
    cout << cpputil::classname_of<class_d>() << endl;
    cout << cpputil::classname_of<class_e>() << endl;
    cout << cpputil::classname_of<class_f>() << endl;

    return 0;
}
class_a
class_b
class_c
class_d
class_e free function should take priority
7class_f

class_a
class_b
class_c
class_d
class_e free function should take priority
7class_f