【Json11源码阅读】09 问题解答,Part_7

// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)  
template <class M, typename std::enable_if<
    std::is_constructible<std::string, typename M::key_type>::value
    && std::is_constructible<Json, typename M::mapped_type>::value,
        int>::type = 0>  
Json(const M & m) : Json(object(m.begin(), m.end())) {}           

注释说,只要传入一个map-like的对象就可以,这是怎么做到的?

// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)  
template <class V, typename std::enable_if<
    std::is_constructible<Json, typename V::value_type>::value,
        int>::type = 0>  
Json(const V & v) : Json(array(v.begin(), v.end())) {}  

同上,vector-like

首先要理解std::enable_if

http://en.cppreference.com/w/cpp/types/enable_if

它定义在头文件<type_traits>中, 是c++11引入的

template<bool B, class T = void >  
struct enable_if;  

如果B是True,结构体enable_if就会定义一个公有的成员type。使用typedef定义,类型为T,形如

struct enable_if  
{  
    typedef T type;  
};  

如果B是False,则enable_if中就没有type个成员。

所以在

template <class M, typename std::enable_if<
    std::is_constructible<std::string, typename M::key_type>::value
    && std::is_constructible<Json, typename M::mapped_type>::value,
        int>::type = 0>  

这一个大长句中,首先要断句

template <class M, typename std::enable_if< B, int>::type = 0>  

结合前面的知识,这个模板参数列表包含两个参数,其中第二个参数不具名且提供了默认值,并且可以看出第二个参数是一个类型模板参数。

另外,这里隐含要求B必须为True,否则enable_if不包含type成员,而这里又访问了type成员

接下来我们关注B,也就是

std::is_constructible<std::string, typename M::key_type>::value
    && std::is_constructible<Json, typename M::mapped_type>::value

先来看看is_constructible怎么解释

http://en.cppreference.com/w/cpp/types/is_constructible

同样的,它也定义在头文件<type_traits>中, 是c++11引入的

template< class T, class... Args >  
struct is_constructible;  

T可以是对象类型也可以是引用类型,如果类型T能够使用Args作为参数进行构造,则is_constructible的名为value的常量成员值为ture, 否则为false

所以这里就要求:类型M必须具备key_typemapped_type两个成员, 并且

  • key_type可用于构造string
  • mapped_type可用于构造Json

现在再回过去看我们的问题就没那么难理解了

// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)  
template <class M, typename std::enable_if<
    std::is_constructible<std::string, typename M::key_type>::value
    && std::is_constructible<Json, typename M::mapped_type>::value,
        int>::type = 0>  
Json(const M & m) : Json(object(m.begin(), m.end())) {}           

模板参数列表中,第二个参数主要是对M作限制,它要求M:

  • 必须有key_type成员,且key_type类型的对象可用于构造string
  • 必须有mapped_type成员,且mapped_type类型的对象可用于构造Json

另外,在最后一行构造object时,使用了m的begin和end成员,所以m必须具备这两个成员,否则编译失败。

至此,我们知道类型M具备

  • key_type
  • mapped_type
  • begin()
  • end()

所以M是map-like对象

那么另外一句也就好解释了,留给大家

// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)  
template <class V, typename std::enable_if<
    std::is_constructible<Json, typename V::value_type>::value,
        int>::type = 0>  
Json(const V & v) : Json(array(v.begin(), v.end())) {}  

END


微信公众号:马志峰的编程笔记

记录一名普通程序员的成长之路

posted @ 2017-04-18 07:18  马志峰  阅读(329)  评论(0编辑  收藏  举报