C++ 使用typeid处理不同的类型

C++ 使用typeid处理不同的类型,c++,sqlite,boost,boost-any,C++,Sqlite,Boost,Boost Any,我试图使用boost::any来封装sqlite返回值。然后我试着写一个循环来打印这些 我的第一个想法是: for(boost::any field: row) { switch(field.type()) { case typeid(double): double value = any_cast<double>(field); ... break; case typeid(other type

我试图使用boost::any来封装sqlite返回值。然后我试着写一个循环来打印这些

我的第一个想法是:

for(boost::any field: row) {
  switch(field.type()) {
      case typeid(double):
          double value = any_cast<double>(field);
          ...
          break;
      case typeid(other type):
          ...
  }
}
for(boost::任意字段:行){
开关(field.type()){
案例类型ID(双):
双值=任何类型(字段);
...
打破
案例类型ID(其他类型):
...
}
}
现在对于有经验的程序员来说,这显然是不可行的,因为typeid返回的是一个实例而不是一个数字id。 经过一些研究,我想我可能会尝试
typeid(…).hash_code()
但是这不够
constexpr
合格(除了哈希冲突的危险)

问题
  • 如果。。。否则…迷宫会根据对象的类型ID处理对象吗

  • 是否有理由认为
    hash\u code
    不是
    const\u expr
    ?这是单独编译目标文件的结果吗
  • std::type_index
    的用途是什么?考虑到它只提供了一些额外的操作符(
    =
    ),为什么不能将其功能与
    std::type_info
    集成

  • 我有一种感觉,您正在寻找增强型和静态访问

    由于没有提到变体,这可能值得作为一个答案发布。演示:

    #include <sstream>
    #include <iostream>
    
    #include <boost/variant.hpp>
    
    using namespace boost;
    
    struct Nil {};
    using blob_t = std::vector<uint8_t>;
    using field_value_t = boost::variant<Nil, double, char const*, long, blob_t/*, boost::date_time, std::vector<uint8_t>*/>;
    
    struct handler : static_visitor<std::string> {
    
        std::string operator()(double)      const { return "double"; }
        std::string operator()(char const*) const { return "C string (ew!)"; }
        std::string operator()(long)        const { return "long"; }
        std::string operator()(blob_t)      const { return "long"; }
        std::string operator()(Nil)         const { return "<NIL>"; }
    
        template<typename T>
        std::string operator()(T const&)    const { throw "Not implemented"; } // TODO proper exception
    };
    
    void handle_field(field_value_t const& value) {
        std::cout << "It's a " << apply_visitor(handler(), value) << "\n";
    }
    
    int main() {
    
        handle_field({});
        handle_field(blob_t { 1,2,3 });
        handle_field("Hello world");
        handle_field(3.14);
    
    }
    
    #包括
    #包括
    #包括
    使用名称空间boost;
    结构Nil{};
    使用blob_t=std::vector;
    使用字段\u值\u t=boost::variant;
    结构处理程序:静态\u访问者{
    std::string操作符()(double)const{return“double”;}
    std::string operator()(char const*)const{return“C string(ew!)”;}
    std::string操作符()(long)const{return“long”;}
    std::string操作符()(blob_t)const{return“long”;}
    std::string操作符()(Nil)常量{return”“;}
    模板
    std::string操作符()(T const&)const{throw“未实现”}//TODO正确异常
    };
    无效句柄字段(字段值常量和值){
    
    std::cout这里是一个类似于boost::any上的静态访问的实现,使用C++11 lambdas:

    #include <iostream>
    #include <type_traits>
    #include <boost/any.hpp>
    
    template <size_t, typename...>
    struct select_type { };
    
    template <size_t index, typename First, typename... Types>
    struct select_type<index, First, Types...> : public select_type<index - 1, Types...> { };
    
    template <typename First, typename... Types>
    struct select_type<0, First, Types...>
    {
        using type = First;
    };
    
    template <typename T>
    struct function_traits : public function_traits<decltype(&T::operator())> { };
    
    template <typename Return, typename Class, typename... Args>
    struct function_traits<Return (Class::*)(Args...) const>
    {
        using result_type = Return;
    
        template <size_t argN>
        using argument_type = select_type<argN, Args...>;
    };
    
    template <typename... Functors>
    struct any_call_impl
    {
        static bool call(boost::any &, Functors const & ...)
        {
            return false;
        }
    
        static bool call(boost::any const &, Functors const & ...)
        {
            return false;
        }
    };
    
    template <typename FirstFunctor, typename... Functors>
    struct any_call_impl<FirstFunctor, Functors...>
    {
        static bool call(boost::any & v, FirstFunctor const & first, Functors const & ... rest)
        {
            using arg = typename function_traits<FirstFunctor>::template argument_type<0>::type;
            using arg_bare = typename std::remove_cv<typename std::remove_reference<arg>::type>::type;
    
            if (v.type() == typeid(arg_bare)) {
                first(*boost::any_cast<arg_bare>(&v));
                return true;
            }
    
            return any_call_impl<Functors...>::call(v, rest...);
        }
    
        static bool call(boost::any const & v, FirstFunctor const & first, Functors const & ... rest)
        {
            using arg = typename function_traits<FirstFunctor>::template argument_type<0>::type;
            using arg_bare = typename std::remove_cv<typename std::remove_reference<arg>::type>::type;
    
            if (v.type() == typeid(arg_bare)) {
                first(*boost::any_cast<arg_bare>(&v));
                return true;
            }
    
            return any_call_impl<Functors...>::call(v, rest...);
        }
    };
    
    template <typename... Functors>
    bool any_call(boost::any & v, Functors const & ... f)
    {
        return any_call_impl<Functors...>::call(v, f...);
    }
    
    template <typename... Functors>
    bool any_call(boost::any const & v, Functors const & ... f)
    {
        return any_call_impl<Functors...>::call(v, f...);
    }
    
    int main(void) {
        boost::any a = 1;
    
        any_call(a,
            [](double d) { std::cout << "double " << d << std::endl; },
            [](int i) { std::cout << "int " << i << std::endl; }
        );
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    模板
    结构选择_类型{};
    模板
    结构选择类型:公共选择类型{};
    模板
    结构选择类型
    {
    使用类型=第一;
    };
    模板
    结构功能特征:公共功能特征{};
    模板
    结构功能特性
    {
    使用结果类型=返回;
    模板
    使用参数(类型=选择类型)


    其思想是传递一个
    boost::any
    boost::any const
    作为
    any\u调用的第一个参数,然后传递多个lambda。将调用参数类型与
    boost::any
    中包含的对象类型匹配的第一个lambda,然后
    any\u调用将返回true。如果没有lambda匹配,
    任何调用
    都将返回false。

    不会
    typeid(field)
    只返回
    boost::any
    hash\u code()的类型ID
    不是
    constexpr
    ,因为
    type\u info
    可能是多态的。有人讨论过提出一种获取类型编译时标识符的方法,但我认为它没有用?使用std::map将type\u索引映射到函子。我将把这项技术留在这里,我指的是“computed goto”是编译
    switch
    的可能方式之一。它使用跳转表,控制变量是用来查找表中的条目的。如果生成的跳转表不够密集,编译器可以选择使用一系列条件编译switch语句(与if/else完全相同)。()
    boost::varaint
    boost::any
    的优势在哪里?标记
    null
    值的最佳方法是什么?(将
    void*
    添加到模板参数?@ted为什么
    void*
    ?它不再是C:)
    struct Nil{};boost::variant
    您已经上路了。更新了示例哦,re
    优势在哪里
    :优势在于您将类型区分留给boost variant,而不会离开类型安全,也不会处理围绕typeid的潜在毛羽。
    #include <iostream>
    #include <type_traits>
    #include <boost/any.hpp>
    
    template <size_t, typename...>
    struct select_type { };
    
    template <size_t index, typename First, typename... Types>
    struct select_type<index, First, Types...> : public select_type<index - 1, Types...> { };
    
    template <typename First, typename... Types>
    struct select_type<0, First, Types...>
    {
        using type = First;
    };
    
    template <typename T>
    struct function_traits : public function_traits<decltype(&T::operator())> { };
    
    template <typename Return, typename Class, typename... Args>
    struct function_traits<Return (Class::*)(Args...) const>
    {
        using result_type = Return;
    
        template <size_t argN>
        using argument_type = select_type<argN, Args...>;
    };
    
    template <typename... Functors>
    struct any_call_impl
    {
        static bool call(boost::any &, Functors const & ...)
        {
            return false;
        }
    
        static bool call(boost::any const &, Functors const & ...)
        {
            return false;
        }
    };
    
    template <typename FirstFunctor, typename... Functors>
    struct any_call_impl<FirstFunctor, Functors...>
    {
        static bool call(boost::any & v, FirstFunctor const & first, Functors const & ... rest)
        {
            using arg = typename function_traits<FirstFunctor>::template argument_type<0>::type;
            using arg_bare = typename std::remove_cv<typename std::remove_reference<arg>::type>::type;
    
            if (v.type() == typeid(arg_bare)) {
                first(*boost::any_cast<arg_bare>(&v));
                return true;
            }
    
            return any_call_impl<Functors...>::call(v, rest...);
        }
    
        static bool call(boost::any const & v, FirstFunctor const & first, Functors const & ... rest)
        {
            using arg = typename function_traits<FirstFunctor>::template argument_type<0>::type;
            using arg_bare = typename std::remove_cv<typename std::remove_reference<arg>::type>::type;
    
            if (v.type() == typeid(arg_bare)) {
                first(*boost::any_cast<arg_bare>(&v));
                return true;
            }
    
            return any_call_impl<Functors...>::call(v, rest...);
        }
    };
    
    template <typename... Functors>
    bool any_call(boost::any & v, Functors const & ... f)
    {
        return any_call_impl<Functors...>::call(v, f...);
    }
    
    template <typename... Functors>
    bool any_call(boost::any const & v, Functors const & ... f)
    {
        return any_call_impl<Functors...>::call(v, f...);
    }
    
    int main(void) {
        boost::any a = 1;
    
        any_call(a,
            [](double d) { std::cout << "double " << d << std::endl; },
            [](int i) { std::cout << "int " << i << std::endl; }
        );
    
        return 0;
    }