【问题标题】:template metaprogramming evaluation模板元编程评估
【发布时间】:2012-05-24 23:29:49
【问题描述】:

所以我有一个模板类,我想接受一个 std::map,其中数据类型是原始指针或 std::unique_ptr。然后在这个类中我想得到底层指针的类型:

typedef typename boost::mpl::if_<
    boost::is_pointer<typename Container::mapped_type>,
    typename Container::mapped_type,
    typename Container::mapped_type::element_type*
>::type data_type

但是,在使用具有原始指针类型的映射实例化类时出现以下错误:

error: 'std::map<int, ValueType*>::mapped_type {aka ValueType*}' is not a class, struct, or union type

在我看来,它正在评估原始指针上的typename Container::mapped_type::element_type*,我认为使用模板元编程它不会在 if_ 成功时评估它。我应该以不同的方式解决这个问题吗?

【问题讨论】:

    标签: c++ boost template-meta-programming boost-mpl


    【解决方案1】:

    你需要一个懒惰if——试试boost::mpl::eval_if而不是boost::mpl::if_

    #include <boost/type_traits/is_pointer.hpp>
    #include <boost/mpl/eval_if.hpp>
    #include <boost/mpl/identity.hpp>
    
    template<typename T>
    struct extract_element_type
    {
        typedef typename T::element_type* type;
    };
    
    template<typename Container>
    struct foo
    {
        typedef typename boost::mpl::eval_if<
            boost::is_pointer<typename Container::mapped_type>,
            boost::mpl::identity<typename Container::mapped_type>,
            extract_element_type<typename Container::mapped_type>
        >::type data_type;
    };
    

    即,当有疑问时,添加一个额外的间接层。

    【讨论】:

    • 谢谢!这行得通,使用惰性 if 是有道理的,但我真的不明白为什么你需要 identity 和 extract_element_type?
    • @grivescorbett :eval_if 不像 if_ 那样直接输入类型,而是采用 产生 类型的一元元函数。所述元函数的惰性求值/实例化是使其按您需要的方式工作的原因。
    • 啊,这是我第一次使用 MPL,谁知道它会这么复杂?
    • @grivescorbett 它变得更糟了! :P