【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
它定义在头文件<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
怎么解释
同样的,它也定义在头文件<type_traits>
中, 是c++11引入的
template< class T, class... Args >
struct is_constructible;
T可以是对象类型也可以是引用类型,如果类型T能够使用Args作为参数进行构造,则is_constructible
的名为value
的常量成员值为ture, 否则为false
所以这里就要求:类型M必须具备key_type
和mapped_type
两个成员, 并且
key_type
可用于构造stringmapped_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
微信公众号:马志峰的编程笔记
记录一名普通程序员的成长之路