├── Chapter1 ├── item4.log ├── item3.aux ├── item3.fls ├── item3.fdb_latexmk ├── chapter1.tex ├── chapter1.log ├── item3.log ├── item2.tex ├── item4.tex ├── item3.tex └── item1.tex ├── .gitignore ├── EffectiveModernCppCN.pdf ├── EffectiveModernCppCN.synctex.gz ├── README.md ├── Chapter2 ├── chapter2.tex └── item6.tex ├── Chapter3 ├── chapter3.tex └── item7.tex ├── EffectiveModernCppCN.out ├── EffectiveModernCppCN.toc ├── EffectiveModernCppCN.tex ├── EffectiveModernCppCN.aux └── EffectiveModernCppCN.log /Chapter1/item4.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter1/item3.aux: -------------------------------------------------------------------------------- 1 | \relax 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Effective-Modern-C-plus-plus.pdf 2 | -------------------------------------------------------------------------------- /EffectiveModernCppCN.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/innooi/EffectiveModernCppCN/HEAD/EffectiveModernCppCN.pdf -------------------------------------------------------------------------------- /EffectiveModernCppCN.synctex.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/innooi/EffectiveModernCppCN/HEAD/EffectiveModernCppCN.synctex.gz -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EffectiveModernCppCN 2 | 3 | 内容是本人翻译的Scott Meyers的《Effective Modern C++》中文版,使用Latex格式编写,目前的进度是条款2。 4 | 5 | 如有有兴趣的朋友希望共同翻译,共同学习,可以联系邮箱shengnics@gmail.com。 6 | 7 | 以上发布的内容纯属个人兴趣,仅供内部技术交流,请勿用作任何商业用途。 8 | -------------------------------------------------------------------------------- /Chapter2/chapter2.tex: -------------------------------------------------------------------------------- 1 | \chapter{auto} 2 | 在概念上,auto被设计得足够简单,但使用起来往往有些意外。相比手动声明类型,auto能够减少字符的输入,同时也防止了类型的声明错误和一部分性能问题。但有些时候auto按照预先的类型推导算法推导出的结果会被程序员认为是错误类型。因此当这种情况发生时,程序员有必要知道怎么用auto产生正确的结果,因为退回到手动声明类型是现代C++应该避免的做法。 3 | 4 | 接下来的这一章深入浅出的探讨了auto。 5 | \input{./Chapter2/item6.tex} 6 | -------------------------------------------------------------------------------- /Chapter1/item3.fls: -------------------------------------------------------------------------------- 1 | PWD /Users/shengni/Documents/EffectiveModernCppCN/Chapter1 2 | INPUT /usr/local/texlive/2014/texmf.cnf 3 | INPUT /usr/local/texlive/2014/texmf-dist/web2c/texmf.cnf 4 | INPUT /usr/local/texlive/2014/texmf-var/web2c/pdftex/pdflatex.fmt 5 | INPUT item3.tex 6 | OUTPUT item3.log 7 | -------------------------------------------------------------------------------- /Chapter3/chapter3.tex: -------------------------------------------------------------------------------- 1 | \chapter{过渡到现代C++} 2 | C++11和C++14有一些很重要的显著特性值得详细讲解,比如auto、智能指针、move语义、lambada表达式和并发控制,而每一点我都单独开创了一章来讲述。虽然需要尽快掌握这些新的语法特性,但是想要成为一名高效率的现代C++程序员必须要循序渐进,而每一步都应该详细分析从C++98过渡到现代C++会面临的问题。比如说:什么时候应该使用大括号而不是小括号来给变量初始化?什么时候声明别名比typedef要好?constexpr和const的区别是什么?const成员函数和线程安全有什么关系?我们能够举出许多这样的例子,接下来的这一章将一个个的解决这些问题。 3 | 4 | \input{./Chapter3/item7.tex} 5 | -------------------------------------------------------------------------------- /Chapter1/item3.fdb_latexmk: -------------------------------------------------------------------------------- 1 | # Fdb version 3 2 | ["pdflatex"] 1435048439 "item3.tex" "item3.pdf" "item3" 1435048439 3 | "/usr/local/texlive/2014/texmf-dist/web2c/texmf.cnf" 1418473959 31908 9e60cc122a23ef93121ea6e29902081d "" 4 | "/usr/local/texlive/2014/texmf-var/web2c/pdftex/pdflatex.fmt" 1427541290 3847283 69bab05ddb67e900f553db8734a3933e "" 5 | "/usr/local/texlive/2014/texmf.cnf" 1427541235 455 5b996dcaa0eb4ef14a83b026bc0a008c "" 6 | "item3.aux" 1435048439 8 a94a2480d3289e625eea47cd1b285758 "" 7 | "item3.tex" 1434908485 12877 855dc748b770a55e2cb2b06ef5a11d66 "" 8 | (generated) 9 | "item3.pdf" 10 | "item3.log" 11 | -------------------------------------------------------------------------------- /EffectiveModernCppCN.out: -------------------------------------------------------------------------------- 1 | \BOOKMARK [0][-]{chapter.1}{类型推导}{}% 1 2 | \BOOKMARK [1][-]{section.1.1}{条款1:理解模板类型推导}{chapter.1}% 2 3 | \BOOKMARK [1][-]{section.1.2}{条款2:理解auto类型推导}{chapter.1}% 3 4 | \BOOKMARK [1][-]{section.1.3}{条款3:理解decltype}{chapter.1}% 4 5 | \BOOKMARK [1][-]{section.1.4}{条款4:掌握如何查看推导类型}{chapter.1}% 5 6 | \BOOKMARK [2][-]{subsection.1.4.1}{IDE编辑器}{section.1.4}% 6 7 | \BOOKMARK [2][-]{subsection.1.4.2}{编译器诊断}{section.1.4}% 7 8 | \BOOKMARK [2][-]{subsection.1.4.3}{运行时输出}{section.1.4}% 8 9 | \BOOKMARK [0][-]{chapter.2}{auto}{}% 9 10 | \BOOKMARK [1][-]{section.2.1}{条款6:当auto无法推导出正确的类型时,使用明确的类型初始化句式}{chapter.2}% 10 11 | -------------------------------------------------------------------------------- /Chapter1/chapter1.tex: -------------------------------------------------------------------------------- 1 | \chapter{类型推导} 2 | C++98有一套单一的类型推导规则:函数模板,C++11对此做了少量的修改,并加入了2种新的方法:一种是{\M auto},另一种是{\M decltype}。C++14则进一步扩展了{\M auto}和{\M decltype}能够使用的语境。类型推断的广泛应用将程序员从繁重的类型拼写工作中解放出来。在源码中某一处的修改能够自动的通过类型推导应用到其他的地方,提升了C++开发的弹性。然而,类型推导也会使得程序更加难以理解,因为编译器做出的类型推导很有可能与你希望的方式不同。 3 | 4 | 因此,如果不深入的理解类型推导的原理,高效地使用现代C++编程是不可能的。因为有太多的场景会用到它:调用函数模板,大多数{\M auto}出现的地方,{\M decltype}表达式中和C++14中神秘的的{\M decltype(auto)}构造应用的地方, 5 | 6 | 本章涵盖了每个C++开发者都应了解的类型推导知识,阐述了模板类型推导是如何工作、{\M auto}在此基础上如何建立规则和{\M decltype}如何按照自己独立的规则工作。其中甚至描述了如何强制令编译器推导的类型结果可见,使你能够确保编译器推导的结果是你所希望的。 7 | 8 | 9 | \input{./Chapter1/item1.tex} 10 | \input{./Chapter1/item2.tex} 11 | \input{./Chapter1/item3.tex} 12 | \input{./Chapter1/item4.tex} -------------------------------------------------------------------------------- /EffectiveModernCppCN.toc: -------------------------------------------------------------------------------- 1 | \contentsline {chapter}{\numberline {1}类型推导}{5}{chapter.1} 2 | \contentsline {section}{\numberline {1.1}条款1:理解模板类型推导}{5}{section.1.1} 3 | \contentsline {section}{\numberline {1.2}条款2:理解auto类型推导}{10}{section.1.2} 4 | \contentsline {section}{\numberline {1.3}条款3:理解decltype}{14}{section.1.3} 5 | \contentsline {section}{\numberline {1.4}条款4:掌握如何查看推导类型}{18}{section.1.4} 6 | \contentsline {subsection}{\numberline {1.4.1}IDE编辑器}{18}{subsection.1.4.1} 7 | \contentsline {subsection}{\numberline {1.4.2}编译器诊断}{18}{subsection.1.4.2} 8 | \contentsline {subsection}{\numberline {1.4.3}运行时输出}{19}{subsection.1.4.3} 9 | \contentsline {chapter}{\numberline {2}auto}{23}{chapter.2} 10 | \contentsline {section}{\numberline {2.1}条款6:当auto无法推导出正确的类型时,使用明确的类型初始化句式}{23}{section.2.1} 11 | -------------------------------------------------------------------------------- /Chapter1/chapter1.log: -------------------------------------------------------------------------------- 1 | This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=pdflatex 2015.3.28) 14 JUN 2015 16:07 2 | entering extended mode 3 | restricted \write18 enabled. 4 | file:line:error style messages enabled. 5 | %&-line parsing enabled. 6 | **chapter1.tex 7 | (./chapter1.tex 8 | LaTeX2e <2014/05/01> 9 | Babel <3.9l> and hyphenation patterns for 79 languages loaded. 10 | ./chapter1.tex:1: Undefined control sequence. 11 | l.1 \chapter 12 | {类型推导} 13 | ? 14 | ./chapter1.tex:1: Emergency stop. 15 | l.1 \chapter 16 | {类型推导} 17 | End of file on the terminal! 18 | 19 | 20 | Here is how much of TeX's memory you used: 21 | 5 strings out of 493109 22 | 131 string characters out of 6135010 23 | 52967 words of memory out of 5000000 24 | 3570 multiletter control sequences out of 15000+600000 25 | 3640 words of font info for 14 fonts, out of 8000000 for 9000 26 | 1141 hyphenation exceptions out of 8191 27 | 5i,0n,1p,37b,8s stack positions out of 5000i,500n,10000p,200000b,80000s 28 | ./chapter1.tex:1: ==> Fatal error occurred, no output PDF file produced! 29 | -------------------------------------------------------------------------------- /Chapter1/item3.log: -------------------------------------------------------------------------------- 1 | This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=pdflatex 2015.3.28) 23 JUN 2015 16:33 2 | entering extended mode 3 | restricted \write18 enabled. 4 | file:line:error style messages enabled. 5 | %&-line parsing enabled. 6 | **item3.tex 7 | (./item3.tex 8 | LaTeX2e <2014/05/01> 9 | Babel <3.9l> and hyphenation patterns for 79 languages loaded. 10 | ./item3.tex:1: Undefined control sequence. 11 | l.1 \section 12 | {条款3:理解decltype} 13 | ? 14 | ./item3.tex:1: Emergency stop. 15 | l.1 \section 16 | {条款3:理解decltype} 17 | End of file on the terminal! 18 | 19 | 20 | Here is how much of TeX's memory you used: 21 | 5 strings out of 493109 22 | 119 string characters out of 6135010 23 | 52967 words of memory out of 5000000 24 | 3570 multiletter control sequences out of 15000+600000 25 | 3640 words of font info for 14 fonts, out of 8000000 for 9000 26 | 1141 hyphenation exceptions out of 8191 27 | 5i,0n,1p,46b,8s stack positions out of 5000i,500n,10000p,200000b,80000s 28 | ./item3.tex:1: ==> Fatal error occurred, no output PDF file produced! 29 | -------------------------------------------------------------------------------- /EffectiveModernCppCN.tex: -------------------------------------------------------------------------------- 1 | %!TEX TS-program = xelatex 2 | %!TEX encoding = UTF-8 Unicode 3 | 4 | \documentclass[8pt,a4paper]{book} 5 | 6 | \usepackage[top=1in, bottom=1in, left=1.25in, right=1.25in]{geometry} 7 | \setlength{\parskip}{0.5\baselineskip} 8 | 9 | \usepackage[linewidth=1pt]{mdframed} 10 | \usepackage{lipsum} 11 | 12 | \usepackage{indentfirst} 13 | \usepackage[colorlinks,linkcolor=black,anchorcolor=blue,citecolor=green]{hyperref} 14 | \setlength{\parindent}{0pt} 15 | 16 | \usepackage{listings} 17 | \usepackage{lipsum} 18 | \usepackage{courier} 19 | \usepackage{lmodern} 20 | 21 | \usepackage{color} 22 | \definecolor{gray}{rgb}{0.8,0.8,0.8} 23 | \usepackage{listings} 24 | %\lstset{numbers=left} 25 | \lstset{language=C++} \lstset{breaklines} 26 | \lstset{extendedchars=false} \lstset{backgroundcolor=\color{white}} 27 | \lstset{keywordstyle=\color{blue}\bfseries} \lstset{frame=none} 28 | \lstset{tabsize=4} \lstset{commentstyle=\color{red}} 29 | \lstset{stringstyle=\emph} 30 | \lstset{frame=single} 31 | 32 | \usepackage{xeCJK} 33 | \setCJKmainfont{STHeitiSC-Light} 34 | \setCJKsansfont{STKaiti} 35 | \setCJKmonofont{STFangsong} 36 | \newfontfamily{\E}{Times-Roman} 37 | \newfontfamily{\M}{PTMono-Regular} 38 | 39 | \begin{document} 40 | 41 | \title{\E Effective Modern C++} 42 | \author{\E Scott Meyers} 43 | 44 | \maketitle 45 | 46 | \tableofcontents 47 | 48 | \input{./Chapter1/chapter1.tex} 49 | \input{./Chapter2/chapter2.tex} 50 | 51 | \end{document} 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /EffectiveModernCppCN.aux: -------------------------------------------------------------------------------- 1 | \relax 2 | \providecommand\zref@newlabel[2]{} 3 | \providecommand\hyper@newdestlabel[2]{} 4 | \providecommand\HyperFirstAtBeginDocument{\AtBeginDocument} 5 | \HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined 6 | \global\let\oldcontentsline\contentsline 7 | \gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} 8 | \global\let\oldnewlabel\newlabel 9 | \gdef\newlabel#1#2{\newlabelxx{#1}#2} 10 | \gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} 11 | \AtEndDocument{\ifx\hyper@anchor\@undefined 12 | \let\contentsline\oldcontentsline 13 | \let\newlabel\oldnewlabel 14 | \fi} 15 | \fi} 16 | \global\let\hyper@last\relax 17 | \gdef\HyperFirstAtBeginDocument#1{#1} 18 | \providecommand*\HyPL@Entry[1]{} 19 | \HyPL@Entry{0<>} 20 | \@writefile{toc}{\contentsline {chapter}{\numberline {1}类型推导}{5}{chapter.1}} 21 | \@writefile{lof}{\addvspace {10\p@ }} 22 | \@writefile{lot}{\addvspace {10\p@ }} 23 | \@writefile{toc}{\contentsline {section}{\numberline {1.1}条款1:理解模板类型推导}{5}{section.1.1}} 24 | \zref@newlabel{mdf@pagelabel-1}{\default{1.1}\page{10}\abspage{10}\mdf@pagevalue{10}} 25 | \@writefile{toc}{\contentsline {section}{\numberline {1.2}条款2:理解auto类型推导}{10}{section.1.2}} 26 | \zref@newlabel{mdf@pagelabel-2}{\default{1.2}\page{14}\abspage{14}\mdf@pagevalue{14}} 27 | \@writefile{toc}{\contentsline {section}{\numberline {1.3}条款3:理解decltype}{14}{section.1.3}} 28 | \zref@newlabel{mdf@pagelabel-3}{\default{1.3}\page{18}\abspage{18}\mdf@pagevalue{18}} 29 | \@writefile{toc}{\contentsline {section}{\numberline {1.4}条款4:掌握如何查看推导类型}{18}{section.1.4}} 30 | \@writefile{toc}{\contentsline {subsection}{\numberline {1.4.1}IDE编辑器}{18}{subsection.1.4.1}} 31 | \@writefile{toc}{\contentsline {subsection}{\numberline {1.4.2}编译器诊断}{18}{subsection.1.4.2}} 32 | \@writefile{toc}{\contentsline {subsection}{\numberline {1.4.3}运行时输出}{19}{subsection.1.4.3}} 33 | \zref@newlabel{mdf@pagelabel-4}{\default{1.4.3}\page{21}\abspage{21}\mdf@pagevalue{21}} 34 | \@writefile{toc}{\contentsline {chapter}{\numberline {2}auto}{23}{chapter.2}} 35 | \@writefile{lof}{\addvspace {10\p@ }} 36 | \@writefile{lot}{\addvspace {10\p@ }} 37 | \@writefile{toc}{\contentsline {section}{\numberline {2.1}条款6:当auto无法推导出正确的类型时,使用明确的类型初始化句式}{23}{section.2.1}} 38 | \zref@newlabel{mdf@pagelabel-5}{\default{2.1}\page{26}\abspage{26}\mdf@pagevalue{26}} 39 | -------------------------------------------------------------------------------- /Chapter1/item2.tex: -------------------------------------------------------------------------------- 1 | \section{条款2:理解auto类型推导} 2 | 3 | 如果你已经阅读了条款1,那么你几乎已经掌握了关于auto类型推导的全部知识,因为除了一个例外之外,auto类型推导几乎就是模板类型推导。但是怎么会呢?模板类型推导包括了模板、函数和形参,但是auto并不处理它们中的任一个。 4 | 5 | 事实确实如此,但是也并没有关系。模板类型推导和auto类型推导之间存在一个映射。通过一种逐字逐句的算法进行互相转换。 6 | 7 | 在条款1中,模板类型推导使用了如下的函数模板: 8 | 9 | \begin{lstlisting} 10 | template 11 | void f(ParamType param); 12 | \end{lstlisting} 13 | 14 | 和如下的函数调用: 15 | 16 | \begin{lstlisting} 17 | f(expr); //使用表达式调用f 18 | \end{lstlisting} 19 | 20 | 在f的函数调用中,编译器使用expr去推导T和ParamType的类型。当一个变量使用auto声明时,auto扮演了模板中T的角色,变量的类型说明符(specifier)则扮演了ParamType的角色。这里用以下的例子能够更好的描述这个情形: 21 | 22 | \begin{lstlisting} 23 | auto x = 27; 24 | \end{lstlisting} 25 | 26 | 这里x的类型说明符就是auto本身。从另一方面来讲,在这个声明中, 27 | 28 | \begin{lstlisting} 29 | const auto cx = x; 30 | \end{lstlisting} 31 | 32 | 的类型说明符是const auto。并且在这里, 33 | 34 | \begin{lstlisting} 35 | const auto& rx = x; 36 | \end{lstlisting} 37 | 38 | 的类型描述符是const auto\&。为了推导例子中x,cx和rx的类型,编译器会认为每个声明都是一个模板,并且按照模板的方式来初始化表达式: 39 | 40 | \begin{lstlisting} 41 | template 42 | void func_for_x(T param); //推导x类型的概念模板(conceptual template) 43 | 44 | func_for_x(27); //概念调用:param的推导类型是x的类型 45 | 46 | template 47 | void func_for_x(const T param); //推导cx类型的概念模板 48 | 49 | func_for_cx(x); //概念调用:param的推导类型是cx的类型 50 | 51 | template 52 | void func_for_rx(const T& param); //推导rx类型的概念模板 53 | 54 | func_for_rx(x); //概念调用:param的推导类型是rx的类型 55 | \end{lstlisting} 56 | 57 | 如我所说,除了一个例外外,auto的类型推导与模板的类型推导规则一样。 58 | 59 | 条款1基于ParamType的特点、函数模板中param的类型描述符,将模板类型的推导分为3种情形。在使用auto的变量推导中,类型描述符取代了ParamType的位置,因此这里同样也有3种情形: 60 | 61 | \begin{itemize} 62 | \item{情形1:类型描述符是一个指针或引用,但不是一个通用引用。} 63 | \item{情形2:类型描述符是一个通用引用。} 64 | \item{情形3:类型描述符既不是一个指针,也不是一个引用。} 65 | \end{itemize} 66 | 67 | 我们已经看到了情形1和情形3: 68 | 69 | \begin{lstlisting} 70 | auto x = 27; //情形3,x不是指针,也不是引用。 71 | 72 | const auto cx = x; //情形3,cx也不是。 73 | 74 | const auto& rx = x; //情形1,rx是一个非通用引用。 75 | \end{lstlisting} 76 | 77 | 情形2与你期望的一样: 78 | 79 | \begin{lstlisting} 80 | auto&& uref1 = x; //x是一个int类型的左值表达式,所以uref1是int& 81 | 82 | auto&& uref2 = cx; //cx是一个const int类型的左值表达式,所以uref2是const int & 83 | 84 | auto&& uref3 = 27; //27是一个int类型的右值表达式,所以uref3是int&& 85 | \end{lstlisting} 86 | 87 | 条款1总结了数组和函数如何退化为非引用类型指针的类型描述符。这种情形也在auto类型推断中发生了: 88 | 89 | \begin{lstlisting} 90 | const char name[] = "R. N. Briggs"; //name的类型是const char[13] 91 | 92 | auto arr1 = name; //arr1的类型是const char * 93 | 94 | auto& arr2 = name; //arr2的类型是const char &[13] 95 | 96 | void someFunc(int, double); //someFunc是一个void(int, double)类型的函数 97 | 98 | auto func1 = someFunc; //func1的类型是void(*)(int, double) 99 | 100 | auto& func2 = someFunc; //func2的类型是void(&)(int, double) 101 | \end{lstlisting} 102 | 103 | 如你所见,auto类型推导与模板类型推导非常相似。它们就像是硬币的两边。 104 | 105 | 除了一个例外。我们将会通过一个例子开始:你希望声明一个初值为27的int对象,C++98给了2种方法: 106 | 107 | \begin{lstlisting} 108 | int x1 = 27; 109 | int x2(27); 110 | \end{lstlisting} 111 | 112 | 通过C++11中的同意初始化(Uniform Initialzation),加入了这些方法: 113 | 114 | \begin{lstlisting} 115 | int x3 = {27}; 116 | int x4{27}; 117 | \end{lstlisting} 118 | 119 | 总共使用了4种语法,获得了同样的结果:一个初值为27的int对象。 120 | 121 | 但如条款5中描述的那样,使用auto类型相较于使用固定类型声明变量有许多好处。因此使用auto替换上述例子中的int将会非常愉快的。简单的文本替换后,变成了如下代码: 122 | 123 | \begin{lstlisting} 124 | auto x1 = 27; 125 | auto x2(27); 126 | auto x3 = { 27 }; 127 | auto x4{ 27 }; 128 | \end{lstlisting} 129 | 130 | 这些声明都能够通过编译,但是它们却并不代表相同的含义。前两个声明确实使用27声明了1个int类型的变量。然而后两个却是声明了一个拥有一个元素27的std::initializer\_list类型的变量! 131 | 132 | \begin{lstlisting} 133 | auto x1 = 27; //类型是int,值是27 134 | auto x2(27); //同上 135 | auto x3 = { 27 }; //类型是std::initializer_list,值是{27} 136 | auto x4{ 27 }; //同上 137 | \end{lstlisting} 138 | 139 | 这种情形是源于auto的特殊类型推导规则。当一个auto声明的变量的初始化器(Initializer)放置在一对大括号中时,这个变量的推导类型是的std::initializer\_list。如果这个类型不能被推导(例如大括号中的值都是不同类型的),这段代码将会无法通过编译。 140 | 141 | \begin{lstlisting} 142 | auto x5 = {1, 2, 3.0}; //错误!不能为std::initializer_list推导T 143 | \end{lstlisting} 144 | 145 | 如注释所指出的那样,在这种情形中,类型推导失败了。但是理解在这个地方实际上发生了两种类型的类型推导是很重要的。一种源于auto的使用:x5的类型必须被推导。因为x5的初始化器在大括号中,所以x5必须被推断为std::initializer\_list。第二种则是,因为std::initializer\_list是一个模板,std::initializer\_list的为某种类型的T实例化,这也意味着T的类型必须被推导。上述的类型推导是因为第二种:模板类型推导而失败的,因为大括号中的初始化器中的元素有多种类型。 146 | 147 | 对于大括号初始化器的不同的处理方式是auto类型推导和模板类型推导唯一不同的地方。当auto声明的变量被大括号初始化器初始化时,推导出的类型是std::initializer\_list。但是如果相应的模板被传入一个相同的初始化器时,类型推导会失败,代码无法通过编译。 148 | 149 | \begin{lstlisting} 150 | auto x = {11, 23, 9} //x的类型是std::initializer_list 151 | 152 | template 153 | void f(T param); //与x声明等价的模板形参声明 154 | 155 | f({11, 23, 9}); //错误,无法为T推导类型 156 | \end{lstlisting} 157 | 158 | 然而,当你指定形参的类型是std::initializer\_list时,模板类型推导规则就会成功推导出T的类型: 159 | 160 | \begin{lstlisting} 161 | template 162 | void f(std::initializer_list initList); 163 | 164 | f({11, 23, 9}); 165 | //T被推导为int,initList的类型是std::initializer_list 166 | \end{lstlisting} 167 | 168 | 所以auto和模板类型推导的唯一差别就是:auto假定大括号初始化器代表着std::initializer\_list,而模板类型则不同。 169 | 170 | 你可能希望知道为什么auto类型推导对于大括号初始化器使用了特别的规则,但是模板类型推导没有。我也想知道,但是不幸的是,我没有找到一个方便的解释。因为规则就是规则,这意味着你在使用auto声明一个变量,并使用一个大括号初始化器时必须记住:推导出的类型一定是std::initializer\_list。如果你想更深入的使用统一的集合初始化时,你就更要牢记这一点。C++11中一个最经典的错误就是程序员意外的声明了一个std::initializer\_list类型的变量,但他们的本意却是想声明一个其他类型的变量。错误造成的主要原因是一些程序员只有当必要的时候,才使用大括号初始化器进行初始化。(将会在条款7中详细讨论。) 171 | 172 | 对于C++11来说,这已经是一个完整的故事了,但是对于C++14,故事还没有结束,C++14允许auto来表示一个函数的返回值的类型(见条款3),并且C++14的lambda表达式可以在参数的声明时使用auto。不管怎样,这些auto的使用,采用的都是模板类型推导的规则,而不是auto类型推导规则,这意味着,大括号的初始化式会造成类型推导的失败,所以一个带有auto返回类型的函数如果返回一个大括号的初始化式将不会通过编译。 173 | 174 | \begin{lstlisting} 175 | auto createInitList() 176 | { 177 | return {1, 2, 3}; //错误,不能够推导类型f{1, 2, 3} 178 | } 179 | \end{lstlisting} 180 | 181 | 同样,规则也适用于当auto用于C++14的lambda的参数类型说明符时: 182 | 183 | \begin{lstlisting} 184 | std::vector v; 185 | ... 186 | 187 | auto resetV = 188 | [&V](const auto& newValue) { v = newValue; }; //C++14 189 | ... 190 | 191 | resetV( {1, 2, 3} ); //错误,不能够推导类型f{1, 2, 3} 192 | \end{lstlisting} 193 | 194 | \begin{mdframed} 195 | 请记住: 196 | \begin{itemize} 197 | \item{auto类型推导规则通常与模板类型推导相同,但是auto类型推导假定1个大括号初始化器代表着std::initializer\_list,而模板类型推导不然。} 198 | \item{当auto是一个函数的返回值类型或是一个lambda传递形参类型时,使用模板类型推导规则,而不是auto类型推导规则。} 199 | \end{itemize} 200 | \end{mdframed} 201 | -------------------------------------------------------------------------------- /Chapter1/item4.tex: -------------------------------------------------------------------------------- 1 | \section{条款4:掌握如何查看推导类型} 2 | 3 | 如何选择合适的、用于查看类型推导结果的工具,取决于你在软件开发过程中所处于的阶段。我们将探讨其中的三种可能性:第一种是在编辑代码时获取类型推导信息,第二种是编译代码时获取,最后一种是运行时过程中获取。 4 | 5 | \subsection{IDE编辑器} 6 | 当你将你的光标放置在实体的附件时,IDE中的编辑器往往能够标注出代码中实体的类型(例如:变量,形参,函数等)。以下面的代码为例; 7 | 8 | \begin{lstlisting} 9 | const int theAnswer = 42; 10 | 11 | auto x = theAnswer; 12 | auto y = &theAndwer; 13 | \end{lstlisting} 14 | 15 | 一个IDE的编辑器将会显示x的推导类型是int,而y的推导类型是const int*。 16 | 17 | 此时此刻,你的代码实际上也处于某种已编译的状态,因为这样IDE才能够通过编译器获取这些信息。如果编译器不能够在此时分析得到足够的类型推导信息,那么IDE也不能够告诉你类型推导的结果。 18 | 19 | 对于像int这样的简单类型,IDE通常能够获得正确的结果。然而,我们很快就会发现,当使用了复杂类型时,IDE所显示的结果可能就不会有什么作用了。 20 | 21 | \subsection{编译器诊断} 22 | 23 | 利用某种导致编译错误的手段,是一个高效的使用编译器获取类型推导结果的方法。问题的错误提示信息实际上就会暗示是什么类型所导致的。 24 | 25 | 举个例子,我们想要推导前面例子中x和y的类型。首先声明一个我们并没有定义的模板类,就像这样: 26 | 27 | \begin{lstlisting} 28 | template //仅为TD声明 29 | class TD; //TD的意思是类型显示器 30 | \end{lstlisting} 31 | 32 | 当尝试实例化这个模板时,编译器会引发一个错误。因为现在并没有用于实例化的模板定义。为了查看x和y的类型,于是使用它们的类型实例化TD: 33 | 34 | \begin{lstlisting} 35 | TD xType; //显示的错误将会包括x和y的类型 36 | TD yType; 37 | \end{lstlisting} 38 | 39 | 我使用了形如vaiableNameType这样的变量名,因为这样所引出的错误消息将引导我找到想要获取的的信息。对于上面的代码,我的一种编译器生成了如下的诊断信息: 40 | 41 | \begin{lstlisting} 42 | error: aggregate 'TD xType' has incomplete type and cannot be defined 43 | error: aggregate 'TD yType' has incomplete type and cannot be defined 44 | \end{lstlisting} 45 | 46 | 另一种编译器使用另一种形式显示了同样的信息: 47 | 48 | \begin{lstlisting} 49 | error: 'xType' use undefined class 'TD' 50 | error: 'yType' use undefined class 'TD' 51 | \end{lstlisting} 52 | 53 | 仅仅只是不同的格式。通过这种技术,我所测试的所有编译器都产生我所需要的类型信息。 54 | 55 | \subsection{运行时输出} 56 | 使用printf手段显示类型的信息只有在运行时才能体现出来(尽管我并不推荐你使用printf),但是这种手段能够完整地控制输出格式。使用文本表示的唯一困难就是如何合适的显示。你一定会觉得,“这有什么难的,使用typeid和std::type\_info::name就能够轻松解决了”。为了能够查看x和y的类型推导,你可能会写出下面的代码: 57 | 58 | \begin{lstlisting} 59 | std::cout << typeid(x).name << '\n'; //显示x和y的类型 60 | std::cout << typeid(y).name << '\n'; 61 | \end{lstlisting} 62 | 63 | 这个方法依赖于这样一个事实:对对象x和y使用typeid函数将会返回一个std::type\_info对象,而std::type\_info对象有一个成员函数name,将会产生一个C-style的字符串(如const char *)用于表示类型的名字。 64 | 65 | 调用std::type\_info::name并不保证返回正确的结果,但是一定程度上会有所帮助。其帮助的等级也会有所不同。例如,GNU和Clang的编译器汇报x的类型是“i”,y的类型是“PKi”。一旦你理解了这些,你就会明白这些输出是有意义的。“i”表示“int”,而“PK”表示“pointer to const”(两个编译器都支持c++filt这个工具,用于解码这些“损坏(mangled)”类型)。微软的编译器产生了更少的输出:“int”表示x,而“int const *”表示y。 66 | 67 | 这些对于x和y的推导结果都是正确的,所以你可能会认为类型汇报的问题已经解决了。但是请先别忙,考虑一个更加复杂的情况: 68 | 69 | \begin{lstlisting} 70 | template //被调用的模板函数 71 | void f(const T& param); 72 | 73 | std::vector createVec(); //工厂函数 74 | 75 | const auto vw = createVec(); //使用工厂函数初始化vw 76 | 77 | if (!vw.empty()) { 78 | f(&vw[0]); //调用f 79 | ... 80 | } 81 | \end{lstlisting} 82 | 83 | 这段代码中有一个用户定义类型(Widget),一个STL容器(std::vector),和一个auto变量(vw)。这是一个非常典型的情况,你可能会很想知道你的编译器类型推导的结果。例如,模板类型形参T和f的函数形参。 84 | 85 | 了解问题中得typeid是很容易的。向f函数加入一些代码,你就会看到: 86 | 87 | \begin{lstlisting} 88 | template 89 | void f(const T& param) 90 | { 91 | using std::cout; 92 | cont << "T = " << typeid(T).name() << '\n'; //显示T的类型 93 | cout << "param = " << typeid(param).name() << '\n'; //显示param的类型 94 | } 95 | \end{lstlisting} 96 | 97 | 执行GNU和Clang编译出的代码后输出: 98 | 99 | \begin{lstlisting} 100 | T = PK6Widget 101 | param = PK6Widget 102 | \end{lstlisting} 103 | 104 | 我们现在已经知道,对于这些编译器而言,“PK”代表“pointer to const”,所以唯一神秘的地方就是数字6。这个简单的代表了接下来类名的字符个数。所以编译器告诉我们T和param都是const Widget*类型的。 105 | 106 | 微软的编译器也同意: 107 | 108 | \begin{lstlisting} 109 | T = class Widget const * 110 | param = class Widget const * 111 | \end{lstlisting} 112 | 113 | 3个独立的编译器生成了相同的结果。但是仔细看一下,在模板f中,param的推导类型是const T\&。在这种情况下,T和param拥有相同的类型不是非常奇怪吗?如果T是一个int类型,那么param应该是const int\&,根本不应该是相同的类型。 114 | 115 | 不幸的是,std::type\_info::name的结果并不可靠。在这个例子中,这3个编译器所汇报param类型都是错误的。而且,它们实际上是被要求输出错误的结果,因为std::type\_info::name明确规定了形参类型推导应当被视作如它们作为一个传值传递的参数一样。正如条款1所说的,这意味着如果类型是一个引用,其引用性会被忽略,如果被去掉引用后是静态类型(或volatile)的,那么其静态性(volatileness)也会被忽略。所以这也是为什么param的类型--const Widget * const \&被汇报为const Widget *。首先引用性被忽略,然后指针的静态性也被消除。 116 | 117 | 同样不幸的是,IDE编辑器中显示的类型信息也是不可靠的,或者至少是不那么可用的。还是刚才那个例子,一个我所知道的IDE编辑器对T的上报结果如下: 118 | 119 | \begin{lstlisting} 120 | const std::_Simple_types >::_Alloc>::value_type>::value_type * 121 | \end{lstlisting} 122 | 123 | 同样的编辑器显示param的类型是: 124 | 125 | \begin{lstlisting} 126 | const std::_Simple_types<...>::value_type *const & 127 | \end{lstlisting} 128 | 129 | 比起T类型的类型还是简单一些,但是其中的“...”可能会令你迷惑,直到你意识到了,这是编辑器在告诉你:“我删除了T类型的部分”。运气好的话,你的开发环境应该能比这个做得更好。 130 | 131 | 如果你更倾向于依赖库而不是幸运,当你知道std::type\_info::name和IDE也会出错,而Boost中的TypeIndex库(常被写作Boost.TypeIndex)一定不会出错时,你一定会很高兴。TypeIndex不是C++标准库的一部分,也不是IDE或者类似TD的模板。Boost库是一个跨平台、开源的,其基于一个即使是最多疑的团队也能够接受的协议,这也意味着使用Boost库的可移植性非常接近C++标准库。 132 | 133 | 以下使用Boost.TypeIndex实现的代码: 134 | 135 | \begin{lstlisting} 136 | template 137 | void f(const T& param) 138 | { 139 | using std::cout; 140 | using boost::typeindex::type_id_with_cvr; 141 | 142 | //显示T的类型 143 | cout << "T = " 144 | << type_id_with_cvr().pretty_name(); 145 | << '\n'; 146 | 147 | //显示param的类型 148 | cout << "param = " 149 | << type_id_with_cvr().pretty_name(); 150 | << '\n'; 151 | ... 152 | } 153 | \end{lstlisting} 154 | 155 | 模板函数boost::typeindex::type\_id\_with\_cvr接收一个类型参数,它不会移除任何const, volatile或者引用修饰符(所以函数名带有一个“with\_cvr”)。其返回结果是一个boost::typeindex::type\_index对象中的成员函数pretty\_name生成的类型字符串。 156 | 157 | 在这种实现下,重新考虑一下当使用typeid时param输出的错误类型信息: 158 | 159 | \begin{lstlisting} 160 | std::vector createVec(); //工厂函数 161 | 162 | const auto vw = createVec(); //使用工厂函数初始化vw 163 | 164 | if (!vw.empty()) { 165 | f(&vw[0]); //调用f 166 | ... 167 | } 168 | \end{lstlisting} 169 | 170 | 使用GNU和Clang的编译器编译后。Boost.TypeIndex生成了这样的(精确的)输出: 171 | 172 | \begin{lstlisting} 173 | T = Widget const* 174 | param = Widget const* const& 175 | \end{lstlisting} 176 | 177 | 使用微软编译器也生成了相同的信息: 178 | 179 | \begin{lstlisting} 180 | T = class Widget const* 181 | param = class Widget const* const& 182 | \end{lstlisting} 183 | 184 | 这种近乎一致的表示是很好的,但是也要记住IDE编辑器,编译错误信息或者类似Boost.TypeIndex的库都仅仅只是帮助你查看编译器的推导信息的辅助工具。它们可能会很有用,但是深刻理解条款1-3所带来的好处是不可替代的。 185 | 186 | \begin{mdframed} 187 | 请记住: 188 | \begin{itemize} 189 | \item{使用IDE编辑器,编译错误信息和Boost TypeIndex库可以查看类型推导的结果。} 190 | \item{使用某些工具获取的推导结果不一定是精确的,因此理解C++的类型推导规则仍然是非常重要的。} 191 | \end{itemize} 192 | \end{mdframed} 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /Chapter2/item6.tex: -------------------------------------------------------------------------------- 1 | \section{条款6:当auto无法推导出正确的类型时,使用明确的类型初始化句式} 2 | 3 | 条款5解释了使用auto声明变量类型相比明确声明变量类型所带来的一些技术优势,但有些时候auto的类型推导并不总是如你所愿。举个例子,假设我有一个函数接收Widget作为参数然后返回std::vector,其中每一个bool表示Widget是否拥有某种特性: 4 | 5 | \begin{lstlisting} 6 | std::vector features(const Widget& w); 7 | \end{lstlisting} 8 | 9 | 进一步假设容器中的第5个元素表示Widget是否拥有高优先级。因此我们可以写出这样的代码: 10 | 11 | \begin{lstlisting} 12 | Widget w; 13 | ... 14 | 15 | bool highPriority = features(w)[5]; // 是否拥有高优先级? 16 | ... 17 | 18 | processWidget(w, highPriority); // 根据优先级级别来处理Widget w 19 | \end{lstlisting} 20 | 21 | 这段代码并没有任何错误,可以正常工作。但如果我们做出一个看似无害的修改,把highPriority的类型声明从bool改成auto: 22 | 23 | \begin{lstlisting} 24 | auto highPriority = features(w)[5]; // 是否拥有高优先级? 25 | \end{lstlisting} 26 | 27 | 那么情况就完全变了。所有的代码能够继续通过编译,但是它的行为将变得不可预测: 28 | 29 | \begin{lstlisting} 30 | processWidget(w, highPriority); // 未定义行为! 31 | \end{lstlisting} 32 | 33 | 正如注释指出的那样,现在调用processWidget将造成未定义行为。为什么会这样?答案可能会让你有些惊讶:在使用auto的代码中,highPriority的类型不再是bool了。尽管std::vector在概念上拥有bool变量,但是std::vector的operator[]并不返回这个容器中元素的引用(除了bool,其他的std::vector::operator[]都返回元素的引用)。取而代之的是返回一个std::vector::reference对象。(它是std::vector的嵌套类) 34 | 35 | 之所以存在std::vector::reference,是因为std::vector需要指定它作为bool的打包形式。如果改用一个bit表示bool,std::vector的operator[]将存在一个明显的问题:对于任意std::vector,operator[]理应返回一个T\&,但C++并不支持对bit的引用。既然不能返回一个bool\&,于是std::vector的operator[]便返回一个看起来像bool的对象。为了实现这个目的,std::vector::reference必须能够支持bool\&能够出现的每个上下文。因此在std::vector::reference的特性中,包含了对bool的隐式转换来完成这项工作。(是bool,而不是bool\&。如果要解释std::vec 36 | tor::reference模拟bool\&的行为用到的所有技术将超出了本书的范围,所以我只是简单的指出隐式转换是是其中的一部分) 37 | 38 | 记住这个特性后,我们再来看看原始代码的这部分: 39 | 40 | \begin{lstlisting} 41 | bool highPriority = features(w)[5]; // 明确定义了highPriority的类型 42 | \end{lstlisting} 43 | 44 | 在这里,函数features返回了一个std::vector对象,然后再对它调用operator[]。而operator[]返回的std::vector::reference通过隐式转换为bool来初始化highPriority。所以正如我们的预期,highPriority存储了features返回的std::vector中的第五个元素。 45 | 46 | 与之相反,如果使用auto来声明highPriority: 47 | 48 | \begin{lstlisting} 49 | auto highPriority = features(w)[5]; // 编译器推导highPriority的类型 50 | \end{lstlisting} 51 | 52 | 53 | 同样的,函数features将返回一个std::vector对象,然后再对它调用operator[]。但发生变化的是,highPriority将会被编译器推导成一个std::vector::reference对象,因此highPriority的值根本就不是std::vector中的第五个元素。 54 | 55 | highPriority的值取决于std::vector::reference的具体实现。一种实现方式是包括一个指向机器字的指针,加上一个偏移位。结合机器字和偏移位进行偏移就能得到判别值。如果std::vector::reference正如这样实现,那么我们来考虑highPriority的初始化到底意味着什么。 56 | 57 | 对函数features的调用将返回一个临时的std::vector对象。为了讨论方便,我们把这个没有名字的对象称为temp。在temp上调用operator[],将会返回一个拥有机器字指针和偏移位的std::vector::reference对象。而highPriority正是这个对象的拷贝,并且指针指向了与temp[5]相同的机器字。当这个语句执行完后,临时变量temp将会被销毁。因此highPriority将包含一个悬空指针,这是导致函数processWidget的产生未定义行为的根本原因: 58 | 59 | \begin{lstlisting} 60 | processWidget(w, highPriority); // 未定义行为! 61 | // highPriority包含悬空指针 62 | \end{lstlisting} 63 | 64 | std::vector::reference是一个代理类的例子:代理类是一种为了模仿和增强其他类的行为而创造的类。代理类有多种用途,std::vector::reference的作用就是把std::vector的operator[]返回值模拟成bool。再例如,标准库中的智能指针就是在指针的基础上扩充了资源管理的代理类。事实上,代理类的应用几乎无处不在,而“代理”也是设计模式领域经久不衰的模式之一。 65 | 66 | 有些代理类被设计成用户透明,例如std::shared\_ptr和std::unique\_ptr。其他的代理类则被设计成或多或少程度上的不可见,std::vector::reference就是一个不可见代理的例子,同样的还有std::bitset::reference。 67 | 68 | 在C++库中还有一部分代理类使用了被称为表达式模板的技术,这些库的目的通常是为了提升数值运算的效率。例如,假如有一个类Matrix和几个Matrix对象m1、m2、m3、m4,那么表达式: 69 | 70 | \begin{lstlisting} 71 | Matrix sum = m1 + m2 + m3 + m4; 72 | \end{lstlisting} 73 | 74 | 在operator+中使用代理类相比直接返回运算结果能够提升极大的效率,因为operator+返回类似于Sum的代理类相比直接返回Matrix对象的开销更小。正如std::vector::reference和bool的关系,Sum能够通过隐式转换成为Matrix,因此表达式中的等号右边能够给sum准确的赋值。(这个赋值的对象通常会对整个运算式编码,最终成为Sum,Matrix>, Matrix>的形式,这个结果也应该对用户不可见) 75 | 76 | 作为基本规则,不可见的代理类通常会造成auto类型推导上的问题。这些类一般情况下会在语句执行完后当场销毁,因此定义变量来存储和使用这样的代理类对象违反了基本的库设计前提。这也是为什么std::vector::reference会造成未定义行为的根本原因。 77 | 78 | 因而你肯定特别想避免这类语句: 79 | 80 | \begin{lstlisting} 81 | auto someVar = expression of "invisible" proxy class type; 82 | // 生成不可见代理类对象的表达式 83 | \end{lstlisting} 84 | 85 | 但是你又怎能轻易识别出代码是否使用了这样的代理类呢?在软件开发中使用代理类的目的并不是向程序员宣扬它们的存在,因为它们至少在概念上应该是不可见的。但是如果你一旦发现了这样的代理类,你真的想要扔掉auto,以及我们在条款5中展示的那些优势吗? 86 | 87 | 首先让我们来看看你是怎样发现代理类的。尽管不可见的代理类被设计成不会被程序员在日常使用中发现,但是库代码通常会在文档中标记出它们的存在。如果你对库的基本设计原则越熟悉,那么你就越不可能被库中的代理类所蒙蔽。 88 | 89 | 另一方面,头文件也填补了文档的缺失。源代码中的代理类不可能被完全封装,它们总是会暴露在函数调用的返回值上,所以函数签名通常能够反映它们的存在。这是std::vector::operator[]的一个实现例子: 90 | 91 | \begin{lstlisting} 92 | namespace std { // 来自C++标准库 93 | template 94 | class vector { 95 | public: 96 | ... 97 | class reference { ... }; 98 | reference operator[](size_type n); 99 | ... 100 | }; 101 | } 102 | \end{lstlisting} 103 | 104 | 如果你知道std::vector的operator[]通常会返回T\&,那么这个不常见的返回值就暴露了它正在使用代理类,留意你正在使用的接口通常能够揭露这些代理类的存在。 105 | 106 | 实际上,很多开发者发现代理类的存在,基本上是由于试图追踪神秘的编译错误或者调试单元测试的意外结果。不管你是怎么发现它们的,一旦auto注定会将类型错误的推导成代理类,而非这个对象本身,那么你就应该考虑放弃使用auto。在这个问题上,auto并不是罪魁祸首,真正错误的是auto没有推导出我们想要的类型。所以解决方案应该是强制性的进行正确的类型推导,这种方法我称之为明确的类型初始化句式。 107 | 108 | 明确的类型初始化句式指的是用auto声明一个变量,然后把初始化表达式转换成你想要auto推倒出的类型。举例来说,用它给highPriority赋值成bool: 109 | 110 | \begin{lstlisting} 111 | auto highPriority = static_cast(features(w)[5]); 112 | \end{lstlisting} 113 | 114 | 这里features(w)[5]依然返回一个std::vector::reference对象,但是类型转换将表达式转型成了bool,因此auto能够将highPriority的类型推导成bool。在运行过程中,std::vector::operator[]将返回的std::vector::reference对象转换成了支持的类型bool。而在这个转换过程中,对std::vector::reference的解引用是合法的,这样就避免了我们先前的未定义行为。最终highPriority就被正确的赋值为数组中的第5个元素,类型为bool。 115 | 116 | 至于Matrix这个例子,明确的类型初始化句式应该是这样: 117 | 118 | \begin{lstlisting} 119 | auto sum = static_cast(m1 + m2 + m3 + m4); 120 | \end{lstlisting} 121 | 122 | 明确的类型初始化句式的应用并不仅仅局限于代理类,它也适用于去强调声明变量的类型与初始化表达式的返回值类型不同。假如你有一个计算误差值的函数: 123 | 124 | \begin{lstlisting} 125 | double calcEpsilon(); // 返回误差值 126 | \end{lstlisting} 127 | 128 | 函数calcEpsilon的返回值类型为double。假如你的程序能够接受精度损失,并且使用float相比double是更好的选择,那么你可能会用float来存储calcEpsilon的结果: 129 | 130 | \begin{lstlisting} 131 | float ep = calcEpsilon(); // float隐式转换成double 132 | \end{lstlisting} 133 | 134 | 但是这样的代码很难说明程序员的做法是故意丢弃了函数返回值的精度。不同的是,明确的类型初始化句式可以这样写: 135 | 136 | \begin{lstlisting} 137 | auto ep = static_cast(calcEpsilon()); 138 | \end{lstlisting} 139 | 140 | 在相同的情况下,这种写法个更能够说明是故意丢弃精度的做法。假如你需要计算随机访问容器(例如std::vector、std::deque或std::array)中某个元素的序号,并且给定了一个0.0到1.0之间的double值来表示这个元素在容器中的位置比例。(0.5表示在容器正中间)进一步假设计算的结果会被赋值给一个int,来表示元素的序号。如果容器的名字为c,double值为d,那么计算序号的语句可以这样写: 141 | 142 | \begin{lstlisting} 143 | int index = d * c.size(); 144 | \end{lstlisting} 145 | 146 | 但是这种写法隐藏了你想要把double转型成int的本意,然而明确的类型初始化句式让整件事变得明朗: 147 | 148 | \begin{lstlisting} 149 | auto index = static_cast(d * c.size()); 150 | \end{lstlisting} 151 | 152 | \begin{mdframed} 153 | 请记住: 154 | \begin{itemize} 155 | \item{不可见的代理类会导致auto给初始化表达式推导出错误的类型。} 156 | \item{明确的类型初始化句式能够让auto推导出你想要的类型。} 157 | \end{itemize} 158 | \end{mdframed} 159 | -------------------------------------------------------------------------------- /Chapter1/item3.tex: -------------------------------------------------------------------------------- 1 | \section{条款3:理解decltype} 2 | 3 | decltype是一个古怪的东西。给定一个名称或者表达式,decltype能告诉你它们的类型。通常用来告诉你它们的类型是不是你想要的。然而有的时候,它也会让你百思不得其解,转而向在线的Q\%A网站求助。 4 | 5 | 我们将从典型的案例开始,它们的结果通常在你的意料之中。与模板类型推导和auto类型推导不同,decltype会返回你给出的名称和表达式准确的类型: 6 | 7 | \begin{lstlisting} 8 | const int i = 0; //decltype(i)返回const int 9 | 10 | bool f(const Widget& w); //decltype(w)返回const Widget& 11 | //decltype(f)返回bool(const Widget &) 12 | 13 | struct Point { 14 | int x, y; 15 | }; 16 | //decltype(Point::x)返回int 17 | //decltype(Point::y)返回int 18 | 19 | Widget w; //decltype(w)返回Widget 20 | 21 | if (f(w)) ... //decltype(f(w))返回bool 22 | 23 | template // std::vector的简单版本 24 | class vector { 25 | public: 26 | … 27 | T& operator[](std::size_t index); 28 | … 29 | }; 30 | 31 | vector v; // decltype(v)返回vector 32 | … 33 | if (v[0] == 0) … // decltype(v[i])返回int& 34 | 35 | \end{lstlisting} 36 | 37 | 看到了吗?并没有什么令人惊讶的。 38 | 39 | 在C++11中,可能decltype的主要用处是声明函数模板,当其的返回类型取决于参数类型时。举个例子,假定我们要写一个函数,它的参数是一个支持[ ]下标访问的容器,函数首先对使用者进行严验证,然后返回下标操作的结果。函数返回值的类型应该与下标操作返回值的类型相同。 40 | 41 | 对一个对象类型为T的容器使用[ ]运算符应当返回一个T\&类型的对象,std::deque就是这样。std::vector几乎也是这样,但只有一个例外,对于std::vector,[ ]运算符并不返回一个bool\&类型的对象,而是返回一个全新的对象,条款6会解释这样的原因。但是重要的是,作用在容器上的[ ]运算符的返回类型取决于这个容器本身。 42 | 43 | decltype让这件事变得简单。下面是我们写的第一个版本,显示了使用decltype推导返回类型的方法,这个模板还可以更精简一些,但是我们先暂时不考虑这个: 44 | 45 | \begin{lstlisting} 46 | template //可以工作 47 | auto authAndAccess(Container& c, Index i) //但是能再精简一些 48 | -> decltype(c[i]) 49 | { 50 | authenticateUser(); 51 | return c[i]; 52 | } 53 | \end{lstlisting} 54 | 55 | 在函数名前使用auto不会进行任何的类型推导,它暗示了C++11的返回类型追踪(trailing return type)语意正在使用。例如:函数的返回类型将在参数列表后声明(在->后面)。追踪返回类型的好处是函数的参数能够在能在返回类型的声明中使用。例如在authAndAccess中,我们使用c和i表明函数的返回类型。如果我们想要将返回类型声明在函数名的前面,但是此时c和i是不可用的,因为它们此时还没有声明。 56 | 57 | 使用例子中的声明方法,authAndAccess能够返回[ ]运算符所返回的类型,如我们想要的一样。 58 | 59 | C++11允许推导单一lambda语句的返回类型,C++14扩展了这个功能,使得所有的lambda和函数表达式都能够使用,包括含有多条语句的函数。这意味着,在C++14中,我们可以不需要返回类型追踪,只需要使用一个auto。在这种形式的声明中,auto确实代表着这里应当表达的类型。这意味着编译器将依据函数的内容来推导函数的返回值类型。 60 | 61 | \begin{lstlisting} 62 | template //c++14支持 63 | auto authAndAccess(Container& c, Index i) //但不是十分正确 64 | { 65 | authenticateUser(); 66 | return c[i]; //由c[i]推断返回类型 67 | } 68 | \end{lstlisting} 69 | 70 | 条款2描述了auto如何推导函数的返回值类型:编译器使用模板类型推导的规则。在这个例子中,就出现了问题。如我们前面所讨论的,[ ]运算符为大多数T类型的容器返回一个T的引用,但是条款1中又说了:在模板类型推导的过程中,引用性在表达式初始化过程中会被忽略。思考一下下面的代码: 71 | 72 | \begin{lstlisting} 73 | std::deque d; 74 | ... 75 | authAndAccess(d, 5) = 10; //函数返回d[5] 76 | //并为其赋值10 77 | //但是不会通过编译! 78 | \end{lstlisting} 79 | 在这里,d[5]应当返回一个int\&,但是auto推导的返回类型会忽略掉引用,因此这里的返回值类型是int。这里的int作为一个函数的返回值,是一个右值表达式,而上面的代码尝试将10赋值给一个右值表达式。这在C++中是禁止的,所以这段代码不能通过编译。 80 | 81 | 为了让authAndAccess能像我们想要的方式工作,我们需要使用decltype为返回值作类型推导,例如:令authAndAccess的返回值类型正好是c[i]表达式所返回的。C++标准的制定者预料到了在某种情况下,类型推导需要使用decltype。所以在C++14中出现了decltype(auto)说明符。刚遇到这种情况时,似乎有一些矛盾。但事实上这是合情合理的,auto指明了了类型需要被推导,而decltype则指示了在推导中所需要使用的规则。因此我们可以这样改写autoAndAccess: 82 | 83 | \begin{lstlisting} 84 | template //c++14支持 85 | decltype(auto) //但还能够改进 86 | authAndAccess(Container& c, Index i) 87 | { 88 | authenticateUser(); 89 | return c[i]; 90 | } 91 | \end{lstlisting} 92 | 93 | 现在authAndAccess的返回值类型将会和c[i]的的返回值完全一致。当c[i]返回一个T\&时,autoAndAccess也会返回一个T\&,而当c[i]返回一个对象时,antuAndAccess也会返回一个对象。 94 | 95 | decltype(auto)的用途并不限于函数的返回值类型。当你想要使用decltype类型推导初始化表达式时,它们也能很方便声明变量: 96 | 97 | \begin{lstlisting} 98 | Widget w; 99 | const Widget& cw = w; 100 | auto myWidget1 = cw; // auto推导出的: 101 | // myWidget1类型是Widget 102 | decltype(auto) myWidget2 = cw; // decltype推导出的: 103 | // myWidget2类型是 104 | // const Widget& 105 | \end{lstlisting} 106 | 107 | 但是我知道这里有两个问题正困扰着你。一个是我之前提到的authAndAccess的改进,让我们现在来解决这个问题。 108 | 109 | 再看一下C++14版的authAndAccess的声明: 110 | \begin{lstlisting} 111 | template 112 | decltype(auto) anthAndAccess(Container& c, Index i); 113 | \end{lstlisting} 114 | 115 | 其中容器形参是通过非const的左值引用传递,因为对一个容器的引用允许我们修改容器其中的元素。但这也意味着不能够向这个函数传递一个右值容器。右值不能够绑定在一个左值引用上(除非是一个const的左值引用,但本例中不是这样的)。 116 | 117 | 诚然,向authAndAccess传递一个右值容器是一个特殊情况。一个右值引用一般是一个临时对象,会在调用authAndAccess的函数的语句后摧毁,这也意味着对该容器的某一个元素的引用将会在调用语句的结束时(一般是authAndAccess返回时)悬空。但是,向anthAndAccess传递一个临时变量仍然是有意义的。一个客户可能只是想要拷贝这个临时变量中的一个元素: 118 | 119 | \begin{lstlisting} 120 | std::deque makeStringDeque(); // 工厂函数 121 | //从makeStringDeque的函数值中拷贝 122 | //容器的第五个元素 123 | auto s = authAndAccess(makeStringDeque(), 5); 124 | \end{lstlisting} 125 | 126 | 支持这种用法意味着我们需要修改authAndAccess的声明,让其既可以接受左值也可以接受右值。这里可以使用重载(一个重载函数声明一个左值引用形参,另一个重载函数声明一个右值引用形参),但是这样我们就要维护两个函数。一种避免这种情况的方法是令authAndAccess使用一个能绑定左值和右值的引用形参,条款24中阐述了这也正好是通用引用所能做的。因此authAndAccess能像这样声明: 127 | 128 | \begin{lstlisting} 129 | template 130 | decltype(auto) anthAndAccess(Container&& c, Index i); //c是一个通用引用 131 | \end{lstlisting} 132 | 133 | 在这个模板里,我们并不知道操作的容器类型,这也意味着我们一样不知道下标所对应对象的类型。对一个为止类型的对象使用传值方法往往会因为不必要的拷贝开销而影响性能,对象分割问题(见条款17)和来自同事的嘲笑。但是根据标准库中的例子(例如std::string, std::vector和std::deque),这种情况下看起来也是合理的,所以我们坚持按值传递。 134 | 135 | 然而,我们需要更新模板的实现方式,依据条款25的警告,将std::forward应用到通用引用上: 136 | 137 | \begin{lstlisting} 138 | template 139 | decltype(auto) 140 | anthAndAccess(Container&& c, Index i); //C++14的最终版本 141 | { 142 | authenticateUser(); 143 | return std::forward(c)[i]; 144 | } 145 | \end{lstlisting} 146 | 147 | 这样就满足了我们所需要的所有要求,但是这段代码需要C++14的编译器。如果你还没有的话,你需要将其改成C++11的版本。这和C++14版本相似,除了你需要自己标注出返回的类型。 148 | 149 | \begin{lstlisting} 150 | template //C++11的 151 | auto // 的最终 152 | authAndAccess(Container&& c, Index i) // 版本 153 | -> decltype(std::forward< Container>(c)[i]) 154 | { 155 | authenticateUser(); 156 | return std::forward(c)[i]; 157 | } 158 | \end{lstlisting} 159 | 160 | 另一个值得对你唠叨的问题我已经标注在了这一条款的开始处了,decltype获得的结果几乎和你期待的一样,这并不奇怪。老实说,你几乎不太可能遇到这个规则的例外情况,除非你需要实现一个任务非常繁重的代码库。 161 | 162 | 为了完全理解decltype的行为,你需要让你自己熟悉一些特殊的情况,大多数在这本书里证明讨论起来会非常的晦涩,但是其中一条能让我们更加理解decltype的使用。 163 | 164 | 对一个变量名使用decltype产生声明这个变量时的类型。有名字的是左值表达式,但这并不影响decltype的行为。因为对于比变量名更复杂的左值表达式,decltype确保推导出的类型总是一个左值的引用,这意味着如果一个左值表达式不同于变量名的类型T,decltype推导出的类型将会是T\&,这几乎不会照成什么影响,因为大多数左值表达式的类型内部通常包含了一个左值引用的限定符,例如,返回左值的函数总是返回一个左值引用。 165 | 166 | 这里有一个值得注意的地方: 167 | 168 | \begin{lstlisting} 169 | int x = 0; 170 | \end{lstlisting} 171 | 172 | x是一个变量的名字,所以decltype(x)的结果是int,但是将名字x用括号包裹起来,”(x)”产生了一个比名字更复杂的表达式,作为一个变量名,x是一个左值,C++同时定义了(x)也是一个左值,因此decltype((x))结果是int\&,将一个变量用括号包裹起来改变了decltype最初的结果! 173 | 174 | 在C++11中,这仅仅会会让人有些奇怪,但是结合C++14中对decltype(auto)的支持后,你对返回语句的一些简单的修改会影响到函数最终推导出的结果。 175 | 176 | \begin{lstlisting} 177 | decltype( auto) f1() 178 | { 179 | int x = 0; 180 | … 181 | return x; // decltype(x) 是 int, 所以f1返回int 182 | } 183 | decltype(auto) f2() 184 | { 185 | int x = 0; 186 | … 187 | return (x); // decltype((x)) 是int&, 所以f2返回int& 188 | } 189 | \end{lstlisting} 190 | 191 | 注意到f2和f1不仅仅是返回类型上的不同,f2返回的是一个局部变量的引用!这种代码的结果是未定义的,你当然不希望发生这种情况。 192 | 193 | 你需要记住的是当你使用decltype(auto)的时候,需要格外注意。一些看起来无关紧要的细节会影响到decltype(auto)推导出的结果,为了确保被推导出的类型是你期待的,可以使用条款4中描述的技术。 194 | 195 | 但同时不要失去对大局的注意,decltype(无论是独立使用还是和auto一起使用)推导的结果可能偶尔让人惊讶,但是这并不会经常发生。通常,decltype的结果和你所期待的类型一样,尤其是当decltype应用在变量名的时候,因为在这种情况下,decltype做的就是提供变量的声明类型。 196 | 197 | \begin{mdframed} 198 | 请记住: 199 | \begin{itemize} 200 | \item{decltype几乎总是返回变量名或是表达式的类型而不会进行任何的修改。} 201 | \item{对于不同于变量名的左值表达式,decltype的结果总是T\&。} 202 | \item{C++14提供了decltype(auto)的支持,比如auto,从它的初始化式中推导类型,但使用decltype的推导规则。} 203 | \end{itemize} 204 | \end{mdframed} 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | -------------------------------------------------------------------------------- /Chapter1/item1.tex: -------------------------------------------------------------------------------- 1 | \section{条款1:理解模板类型推导} 2 | 3 | 大多数复杂系统的用户都只关心系统所带来的功效,却并不关心它的工作原理。从这个层面来看,C++的模板推导是成功的。尽管大多数的程序员对类型推导的工作方式并不了解,但他们使用函数模版传递参数都获得了满意的结果。 4 | 5 | 如果你也是这个群体的一部分,我将告诉你一个好消息和一个坏消息。好消息是模板的类型推导是现代C++中最引人注目功能之一:{\M auto}的基石。如果你对于C++98中的{\M auto}很熟悉,那么C++11中的{\M auto}对你来说也会很熟悉。坏消息是当模板类型推断在有{\M auto}的上下文中使用时,相对于其在其他情况下(简单模板类型中)的应用变得更加令人疑惑了。因此,理解{\M auto}所依赖的模板类型推导的原理是非常重要的。本条款涵盖了该方面你所需要了解的所有知识。 6 | 7 | 如果你愿意忽略少量的伪代码,我们可以思考下面一个函数模板的例子: 8 | 9 | \begin{lstlisting} 10 | template 11 | void f(ParamType param); 12 | \end{lstlisting} 13 | 14 | 函数的调用形如: 15 | 16 | \begin{lstlisting} 17 | f(expr); //使用表达式调用f函数 18 | \end{lstlisting} 19 | 20 | 在编译过程中,编译器使用\textit{expr}推导2个类型:一个是{\M T}另一个是\textit{ParamType}。这2个类型往往是不同的,因为\textit{ParamType}通常都会包含修饰符,如{\M const}或者是引用限定符。例如,如果模板是这样声明的: 21 | 22 | \begin{lstlisting} 23 | template 24 | void f(const T& param); //ParamType是const T&类型 25 | \end{lstlisting} 26 | 27 | 并且我们这样调用: 28 | 29 | \begin{lstlisting} 30 | int x = 0; 31 | 32 | f(x); //调用f,实参是int类型 33 | \end{lstlisting} 34 | 35 | {\M T}被推导为{\M int}类型,但\textit{ParamType}被推导为const int\&。 36 | 37 | 人们通常希望{\M T}的类型推导和传入函数的参数类型是一致的,例如{\M T}的类型与\textit{expr}是相同的。在上述的例子中,就是这种情况:{\M x}是{\M int}类型,{\M T}被推导为{\M int}类型。但并不总是这样,{\M T}的类型推导不仅仅和\textit{expr}的类型有关,也和\textit{ParamType}的类型相关。下面有3个例子: 38 | 39 | \begin{itemize} 40 | \item{\textit{ParamType}是一个指针或者引用,但不是一个通用引用(Universal Reference)。(通用引用在条款24中描述,在这里,你只需要知道它存在,并且和左值引用、右值引用不同。)} 41 | \item{\textit{ParamType}是一个通用引用。} 42 | \item{\textit{ParamType}既不是指针,也不是引用。} 43 | \end{itemize} 44 | 45 | 接下来我们会介绍3种类型推导的情形,每一个调用都会以我们的通用模板为基础: 46 | 47 | \begin{lstlisting} 48 | template 49 | void f(ParamType param); 50 | 51 | f(expr); //从expr中推导T和ParamType的类型 52 | \end{lstlisting} 53 | 54 | \subsection*{情形1:\textit{ParamType}是一个指针或者引用,但不是一个通用引用} 55 | 在这种情况下,类型推导是这样工作的: 56 | 57 | 1. 如果\textit{expr}的类型是一个引用,忽略引用的符号。 58 | 59 | 2. 然后模式匹配expr的类型来决定ParamType的类型从而决定T的类型 60 | 61 | 例如,如果这是我们的模板: 62 | \begin{lstlisting} 63 | template 64 | void f(T& param); //param是一个引用 65 | \end{lstlisting} 66 | 然后我们有如下变量声明: 67 | \begin{lstlisting} 68 | int x = 27; //x是int类型 69 | const int cx = x; //cx是const int类型 70 | const int& rx = x; //rx是x的常量引用 71 | \end{lstlisting} 72 | 73 | 则param和T的类型推导如下: 74 | \begin{lstlisting} 75 | f(x); //T是int,param的类型是int & 76 | 77 | f(cx); //T是const int,param的类型是const int& 78 | 79 | f(rx); //T是const int,param的类型是const int & 80 | \end{lstlisting} 81 | 82 | 在第二个和第三个调用中,注意由于cx和rx是常量类型,T被推导为const int,因此产生了const int\&类型的形参。这对于调用者来说非常重要。当他们传递一个const对象给一个引用形参时,他们希望这个对象仍是不可修改的,例如:形参是对常量的引用。这也是为什么传递一个const对象给一个使用T\&作为形参的模板是安全的:对象的常量性(constness)被推导为了T类型的一部分。 83 | 84 | 在第三个例子中,注意尽管rx的类型是一个引用,T仍被推导为了一个非引用类型。这是因为rx的引用性(reference-ness)在类型推导的过程中被忽略了。 85 | 86 | 这些例子中使用的都是左值引用形参,类型推导同样以相同的方式能够作用于右值引用形参。当然,只有右值的实参可能会被传递给右值引用的形参,但是这对类型推断没有什么影响。 87 | 88 | 如果我们把f的形参由T\&改为const T\&,就会发生一些变化,但也并不令人惊讶。cx和rx的常量性依然被保留,但是因为我们已经假定param的是一个对常量的引用,所以const不再是T类型的一部分了。 89 | \begin{lstlisting} 90 | template 91 | void f(const T& param); //param现在是一个常量引用 92 | 93 | int x = 27; 94 | const int cx = x; 95 | const int &rx = x; 96 | 97 | f(x); //T是int,param的类型是const T& 98 | 99 | f(cx); //T是int,param的类型是const T& 100 | 101 | f(rx); //T是int,param的类型是const T& 102 | \end{lstlisting} 103 | 同样,rx的引用性在类型推导的过程中被忽略。 104 | 105 | 如果param是一个指针(或是指向const的指针)而不是一个引用,规则并没有本质上改变: 106 | 107 | \begin{lstlisting} 108 | template 109 | void f(T* param); //param现在是一个指针 110 | 111 | int x = 27; 112 | const int *px = &x; //px是一个将x视作const int的指针 113 | 114 | f(&x); //T是int,param的类型是int * 115 | f(px); //T是const int,param的类型是const int * 116 | \end{lstlisting} 117 | 现在,你可能发现你自己在不断的打哈欠和点头,因为C++的类型推导在引用和指针形参上工作得如此自然。每件事情都是如此清晰,与你希望的类型推导系统完全一样。 118 | 119 | \subsection*{情形2:\textit{ParamType}是一个通用引用} 120 | 当使用了通用引用后,事情就变得不是那么清楚了。形参似乎被声明为一个一个右值引用(例如:函数模板中的形参被声明为T\&\&),但是它们在传入一个左值实参后的表现却完全不同。完整的故事会在条款24中描述,这里有一个概要的版本。 121 | 122 | \begin{itemize} 123 | \item{如果expr是一个左值表达式,那么T和ParamType都被会推导为左值引用。这是非常不同寻常的。首先这是唯一一种情形:T被推导为一个引用。第二,尽管ParamType被声明为一个右值引用,但是其推导的类型却是一个左值引用。} 124 | \item{如果expr是一个右值表达式,则按照情形1的方式处理。} 125 | \end{itemize} 126 | 127 | 例如: 128 | \begin{lstlisting} 129 | template 130 | void f(T&& param); //param现在是一个通用引用 131 | 132 | int x = 27; //x是int类型 133 | const int cx = x; //cx是const int类型 134 | const int& rx = x; //rx是x的常量引用 135 | 136 | f(x); //x是一个左值表达式,因此T是一个int&,param也是int& 137 | f(px); //px是一个左值表达式,因此T是const int,param是const int & 138 | f(rx); //rx是一个左值表达式,因此T是const int,param是const int & 139 | f(27); //27是一个右值表达式,因此T是一个int,param是int && 140 | \end{lstlisting} 141 | 142 | 条款24清楚的解释了这些情形发生的原因。关键点在于通用引用的类型推导规则取决于形参是左值引用还是右值引用。当使用通用引用时,类型推导规则会区分左值实参和右值实参,而这从来都不会发生在非通用引用上。 143 | 144 | (译者注:以上对左值引用、右值引用、通用引用不太明白的部分可以看\\http://www.cnblogs.com/qicosmos/p/3369940.html学习) 145 | 146 | \subsection*{情形3:\textit{ParamType}既不是指针,也不是引用} 147 | 当ParamType既不是一个指针,也不是一个引用时,我们使用值传递的方式: 148 | \begin{lstlisting} 149 | template 150 | void f(T param); //param通过值传递 151 | \end{lstlisting} 152 | 这意味着param将会成为传递进来的实参的一份拷贝---一个全新的对象。事实上,param成为一个全新的对象指导T如何从expr中推导。 153 | 154 | 1. 与之前一样,如果expr是一个引用,引用的部分会被忽略。 155 | 2. 在忽略了expr的引用部分后,如果expr是一个const,同样也会被忽略。如果它是volatile,也会被忽略。(volatile对象并不常用,它们通常仅用于设备驱动程序的开发。详细内容可见条款40。) 156 | 157 | 因此: 158 | \begin{lstlisting} 159 | int x = 27; //x是int类型 160 | const int cx = x; //cx是const int类型 161 | const int& rx = x; //rx是x的常量引用 162 | 163 | f(x); //T和paramdoiu是int 164 | f(cx); //T和param都是int 165 | f(rx); //T和param都是int 166 | \end{lstlisting} 167 | 168 | 注意尽管cx和rx都是静态变量,但param不是。这是讲得通的,因为param是一个完全独立于cx和rx的对象---它们之一的一份拷贝。事实上,cx和rx不可被修改不会对param产生任何影响。这也是为什么说expr的静态性在类型推导时被忽略:因为expr不可被修改并不意味着它的拷贝也不可被修改。 169 | 170 | 意识到当使用值传递方式时,const(volatile)会被忽略是很重要的。我们看到,对于形参是静态量引用或指针,在类型推导时expr的静态性被保留。但是当expr是一个指向const对象的const指针,而且expr是通过值传递的方式时: 171 | 172 | \begin{lstlisting} 173 | template 174 | void f(T param); //param仍通过值传递 175 | 176 | const char* const ptr = "Fun with pointers"; //ptr是一个指向const对象的const指针 177 | 178 | f(ptr); //实参类型是const char *const 179 | \end{lstlisting} 180 | 181 | 在这里,最右边的const表明了指针是静态的:意味着ptr不能再次指向别的位置,亦或是空。(左边的const表明ptr所指向的字符串不可能被修改。)当ptr传递给f时,指针按位拷贝到param中。同样的,指针自身也是通过值传递。按照使用值传递方式的类型推导规则,ptr的静态性将被忽略,param的类型推导为const char*,一个指向不可被修改的字符串的指针。在类型推导的过程中,ptr所指向内容的静态性被保留,但是ptr自身的静态性在拷贝并创建新指针的过程中丢失了。 182 | 183 | \subsection*{数组实参} 184 | 上面的内容已经涵盖了模板类型推导的主流部分,但还有一些少见的情况值得我们了解。数组类型何指针类型是不同的,尽管一些时候它们是可以交换的。这个谬误主要来源于:在很多语境中,一个数组会退化成其中第一个元素的指针。这种退化允许下面的代码能够通过编译: 185 | \begin{lstlisting} 186 | const char name[] = "J.P.Briggs"; //name的类型是const char[13] 187 | 188 | const char *prtToName = name; //数组退化成指针 189 | \end{lstlisting} 190 | 191 | 在这里,const char*的指针ptrToName使用name初始化,这2个类型(const char *和const char[13])是不同的,但是因为数组-指针退化规则,这段代码可以通过编译。 192 | 193 | 但当一个数组使用值传递方式传给一个模板呢?那会发生什么? 194 | 195 | \begin{lstlisting} 196 | template 197 | void f(T param); //param通过值传递 198 | 199 | f(name); //此时T和param会被推导为什么类型? 200 | \end{lstlisting} 201 | 202 | 一开始我们观察到,函数没有使用数组作为一个形参的,但是下面的语法确实合法的: 203 | 204 | \begin{lstlisting} 205 | void myFunc(int param[]); 206 | \end{lstlisting} 207 | 208 | 但是在这里数组声明被视作一个指针的声明,一位置myFunc的声明实际上等价于: 209 | 210 | \begin{lstlisting} 211 | void myFunc(int *param); //与上面相同的函数 212 | \end{lstlisting} 213 | 214 | 这种数组与指针形参的等价从C中传递到了C++,产生了数组和指针是相同的这种错觉。 215 | 216 | 因为数组形参声明被视作指针形参,当数组以值传递方式入一个函数模板时,其被推导为指针类型。这一位置当调用模板f时,它的类型形参T会被推导为const char *: 217 | 218 | \begin{lstlisting} 219 | f(name); //name是一个数组,但是T推导为const char* 220 | \end{lstlisting} 221 | 222 | 这样现在就出现了一个诡计(curve ball)。尽管函数不能真正的声明其参数是数组类型的,但是它们能够声明参数是数组的引用!这样如果我们修改模板f,令其通过引用接收实参, 223 | 224 | \begin{lstlisting} 225 | template 226 | void f(T& param); //param通过引用传递 227 | \end{lstlisting} 228 | 229 | 然后我们传入一个数组, 230 | 231 | \begin{lstlisting} 232 | f(name); //传递数组给f 233 | \end{lstlisting} 234 | 235 | T的实际类型被推导为一个数组!这种类型将会包括数组的大小,在这个例子中,T的类型是const char[13],而且f的形参类型是const char (\&)[13]。是的,这个语法看起来是有毒的,但是知道这个会让你获得其他人所得不到的罕见分数(一些英文幽默)。 236 | 237 | 有趣的是,声明一个数组的引用能够创建一个能推导出数组元素个数的模板: 238 | 239 | \begin{lstlisting} 240 | //在编译时期间返回数组的大小 241 | template 242 | constexpr std::size_t arraySize(T (&)[N]) noexcept 243 | { 244 | return N; 245 | } 246 | \end{lstlisting} 247 | 248 | 如条款15所描述的,声明一个函数是constexpr的将使其结果在编译期间可用。这让这种用法变得可能:声明一个与之前创建的数组一样大的数组。 249 | 250 | \begin{lstlisting} 251 | int keyVals[] = {1, 3, 7, 9, 11, 22, 35} //keyVals包括7个元素 252 | 253 | int mappedVals[arraySize(coevals)]; //mappedVals也有7个元素。 254 | \end{lstlisting} 255 | 256 | 当然,作为一个现代C++的开发人员,你当然可以用std::array构造一个数组: 257 | 258 | \begin{lstlisting} 259 | std::array mappedVals; //mappedVals的大小是7 260 | \end{lstlisting} 261 | 262 | 至于被声明为noexcept的函数arraySize,这将帮助编译器生成更好的代码,详见条款14。 263 | 264 | \subsection*{函数实参} 265 | 数组类型不是C++中唯一能被退化为指针的类型,函数类型也能够退化为指针类型,我们讨论的任何一个关于类型推导的规则和对数组相关的情形对于函数的类型推导也适用,函数类型会退化为函数的指针,因此: 266 | 267 | \begin{lstlisting} 268 | void someFunc(int, double) //一个类型是void(int, double)的函数 269 | 270 | template 271 | void f1(T param); //值传递方式 272 | 273 | template 274 | void f2(T& param); //引用传递方式 275 | 276 | f1(someFunc); //param被推导为一个函数指针,类型是void(*)(int, double) 277 | 278 | f2(someFunc); //param被推导为一个函数引用,类型是void(&)(int, double) 279 | \end{lstlisting} 280 | 281 | 在实际情况中很难有什么区别,但是当你了解到了数组-指针的退化时,你也同样应该了解到函数-指针的退化。 282 | 283 | 所以你现在明白了:auto相关的模板类型推导规则。如我所说,在一开始它们大多都非常简单直接。唯一需要特殊处理的只有在使用通用引用时,左值表达式会有特别的处理。然而数组和函数的退化规则使得规则变得更加混乱。有时,你可能只是简单的抓住你的编译器,”告诉我,你推导出的类型是什么“,这时候,你可以看看条款4,因为条款4就是讲述如何劝诱你的编译器这么做的。 284 | 285 | \begin{mdframed} 286 | 请记住: 287 | \begin{itemize} 288 | \item{在模板类型推导时,对引用实参会被视作非引用类型的。} 289 | \item{当推导通用引用的形参,左值实参需要特殊的处理。} 290 | \item{当推导使用值传递方式的形参时,const和volatile类型的实参会被忽略掉这两个属性。} 291 | \item{在模板类型推导时,数组和函数实参中会退化为指针类型,除非它们被实例化为引用。} 292 | \end{itemize} 293 | \end{mdframed} 294 | -------------------------------------------------------------------------------- /Chapter3/item7.tex: -------------------------------------------------------------------------------- 1 | \section{条款7:在创造对象时区分()和\{\}} 2 | 3 | 根据开发者的不同视角,C++11内置的对象初始化语择要么是一个多选的尴尬,要么是一个令人迷惑的灾难。作为通用的规则,我们可以通过指定等号、小括号和大括号来进行初始化赋值。 4 | 5 | \begin{lstlisting} 6 | int x(0); // 用小括号初始化 7 | 8 | int y = 0; // 用等号初始化 9 | 10 | int z{ 0 }; // 用大括号初始化 11 | \end{lstlisting} 12 | 13 | 甚至在很多情况下,我们也用以同时使用等号和大括号进行赋值: 14 | 15 | \begin{lstlisting} 16 | int z = { 0 }; // 用等号和大括号初始化 17 | \end{lstlisting} 18 | 19 | 在本条款剩下的内容里,我会忽略掉等号加大括号的语法,因为C++通常将它视为只有大括号的语法。 20 | 21 | 那些认为C++11初始化语法令人迷惑的人会指出,使用等号进行初始化经常会误导C++新手以为发生了赋值,而实际上并非如此。对于像int这种内置类型,它们只有学术上的区别;但是对于用户自定义的类型,区分等号是否会造成赋值就非常重要,因为它们是调用两个不同的函数。 22 | 23 | \begin{lstlisting} 24 | Widget w1; // 调用默认构造函数 25 | 26 | Widget w2 = w1; // 不是赋值,调用拷贝构造函数 27 | 28 | w1 = w2; // 是赋值,调用=操作符 29 | \end{lstlisting} 30 | 31 | 另外在有些情况下,C++98的初始化语法并不能够提供理想的初始化。例如不能直接定义一个STL容器初始就包含一些元素(比如1、3和5)。 32 | 33 | 为了解决多种初始化语法的困扰,同时提供所有初始化情景的支持,C++11引入了统一初始化语法:这种语法能够被应用在所有的地方,至少在概念上如此。因为它是基于大括号的语法,因此我更倾向于称呼它为大括号初始化。在概念上它是统一初始化,但是在形式上是大括号初始化。 34 | 35 | 使用大括号初始化能够让你写出之前不能实现的表达式,比如指定带有初始化值的容器: 36 | 37 | \begin{lstlisting} 38 | std::vector v{ 1, 3, 5 }; // v的初始化内容为1、3、5 39 | \end{lstlisting} 40 | 41 | 大括号初始化还能够用来给非静态成员变量赋予初始值。这个C++11的新能力也能够通过等号来实现,但小括号不行: 42 | 43 | \begin{lstlisting} 44 | class Widget { 45 | ... 46 | private: 47 | int x{ 0 }; // x的初始化值为0 48 | int y = 0; // 与上面相同 49 | int z(0); // 错误! 50 | }; 51 | \end{lstlisting} 52 | 53 | 另一方面,不能复制的对象(比如std::atomics——见条款40)也许能够用大括号或小括号进行初始化,等号却不行: 54 | 55 | \begin{lstlisting} 56 | std::atomic ai1{ 0 }; // 工作正常 57 | std::atomic ai2(0); // 工作正常 58 | std::atomic ai3 = 0; // 错误! 59 | \end{lstlisting} 60 | 61 | 通过上面的例子很容易理解为什么大括号初始化被称为统一初始化,因为在C++提供的三种语法中只有大括号能够支持所有的语境。 62 | 63 | 大括号初始化带来的一个新特性是阻止了内置类型的缩窄转型。如果大括号中的值并不能保证对象能够被正确初始化,这段代码将不能通过编译: 64 | 65 | \begin{lstlisting} 66 | double x, y, z; 67 | 68 | ... 69 | 70 | int sum1{ x + y + z }; // 错误!x+y+z的结果是double而非int 71 | \end{lstlisting} 72 | 73 | 使用小括号和等号赋值并不会引起缩窄转型的检查,因为要考虑到遗留代码的兼容性: 74 | 75 | \begin{lstlisting} 76 | int sum2(x + y + z); // 工作正常(表达式的值转换成int) 77 | 78 | int sum3 = x + y + z; // 工作正常 79 | \end{lstlisting} 80 | 81 | 大括号初始化带来的另一个值得注意的特性是,它对C++语法解析问题免疫。C++的解析规则有一个副作用,那就是任何能够被解析为声明式的语句一定会被解释为声明式,这导致了一个频繁令人苦恼的问题,每当程序员希望定义一个使用默认构造函数进行初始化的变量时,最终都会无意的被解析成一个函数的声明式。这个问题的根源在于如果你想调用带参数的构造函数,可以这样写: 82 | 83 | \begin{lstlisting} 84 | Widget w1(10); // 调用参数为10的构造函数 85 | \end{lstlisting} 86 | 87 | 但是如果你试图使用类似的语法去调用Widget的无参构造函数时,将会声明一个函数而不是对象: 88 | 89 | \begin{lstlisting} 90 | // 令人苦恼的解析问题!声明了一个名为w2并返回Widget的函数 91 | Widget w2(); 92 | \end{lstlisting} 93 | 94 | 由于函数声明不能用大括号作为参数列表,所以使用大括号来默认构造对象并不存在这个问题: 95 | 96 | \begin{lstlisting} 97 | Widget w3{}; // 调用Widget的默认构造函数 98 | \end{lstlisting} 99 | 100 | 因此关于大括号初始化能够引出很多话题。这是一种能够用在大部分情景下的语法,它阻止了隐式的缩窄转型,并且对C++的解析语法问题免疫,简直无所不能!那么为什么这一章的标题不叫“倾向于大括号初始化语法”呢? 101 | 102 | 原因是大括号初始化有一个缺陷,它有时会带来一些意想不到的行为。而这种行为在大括号初始化、std::initializer\_list和重载构造函数三者的纠缠下会变得更加扑朔迷离,它们之间的相互交叉导致代码表面上在做一件事,实际上确是另一件。例如条款2解释了使用auto声明变量时,如果使用大括号初始化将被推导为std::initializer\_list,而使用其他的初始化语法反而能够得到更符合直觉的类型。这个结果导致了你越喜欢auto,你就越缺少热情去使用大括号初始化。 103 | 104 | 在调用构造函数时,只要不涉及std::initializer\_list,大括号和小括号具有相同的语义: 105 | 106 | \begin{lstlisting} 107 | class Widget { 108 | public: 109 | Widget(int i, bool b); 110 | Widget(int i, double d); 111 | 112 | // 没有声明参数为std::initializer_list的构造函数 113 | ... 114 | }; 115 | 116 | Widget w1(10, true); // 调用第一个构造函数 117 | 118 | Widget w2{10, true}; // 调用第一个构造函数 119 | 120 | Widget w3(10, 5.0); // 调用第二个构造函数 121 | 122 | Widget w4{10, 5.0}; // 调用第二个构造函数 123 | \end{lstlisting} 124 | 125 | 但是如果有一个或者更多的构造函数参数被声明为std::initializer\_list,编译器将会有强烈的倾向去调参数为std::initializer\_list的构造函数,作为那些使用大括号初始化语句的解析结果。更糟糕的是,只要编译器能够将大括号初始化表达式转化成std::initializer\_list,它一定会采取这种解析结果。如果上面的Widget类拥有一个参数为std::initializer\_list的构造函数,比如这样: 126 | 127 | \begin{lstlisting} 128 | class Widget { 129 | public: 130 | Widget(int i, bool b); 131 | Widget(int i, double d); 132 | 133 | // 新添加的构造函数 134 | Widget(std::initializer_list il); 135 | ... 136 | }; 137 | \end{lstlisting} 138 | 139 | Widget变量w2和w4将会调用这个新的构造函数,即使相比原来的构造函数, 140 | 元素类型为long double的std::initializer\_list的匹配结果更为糟糕! 141 | 142 | \begin{lstlisting} 143 | Widget w1(10, true); // 使用小括号,调用第一个构造函数 144 | 145 | // 使用大括号,但是调用std::initializer_list的构造函数(10和true被转型成long double) 146 | Widget w2{10, true}; 147 | 148 | Widget w3(10, 5.0); // 使用小括号,调用第二个构造函数 149 | 150 | // 使用大括号,但是调用std::initializer_list的构造函数(10和5.0被转型成long double) 151 | Widget w4{10, 5.0}; 152 | \end{lstlisting} 153 | 154 | 甚至是那些普通的复制和移动的构造函数都会被std::initializer\_list构造函数给劫持: 155 | 156 | \begin{lstlisting} 157 | class Widget { 158 | public: 159 | Widget(int i, bool b); 160 | Widget(int i, double d); 161 | Widget(std::initializer_list il); 162 | 163 | operator float() const; // 转型为float 164 | ... 165 | 166 | }; 167 | 168 | Widget w5(w4); // 使用小括号,调用拷贝构造函数 169 | 170 | // 使用大括号,调用std::initializer_list的构造函数(w4被转型为float,再被转型成long double) 171 | Widget w6{w4}; 172 | 173 | Widget w7(std::move(w4)); // 使用小括号,调用拷贝构造函数 174 | 175 | // 使用大括号,调用std::initializer_list的构造函数(w4被转型为float,再被转型成long double) 176 | Widget w8{std::move(w4)}; 177 | \end{lstlisting} 178 | 179 | 编译器将大括号初始化和接受std::initializer\_list的构造函数匹配的意愿非常强烈,它甚至在std::initializer\_list构造函数不能被调用的情况下,会阻止其他完全匹配的构造函数被调用。例如: 180 | 181 | \begin{lstlisting} 182 | class Widget { 183 | public: 184 | Widget(int i, bool b); 185 | Widget(int i, double d); 186 | Widget(std::initializer_list il); 187 | 188 | ... // 没有隐式转型函数 189 | 190 | }; 191 | 192 | Widget w{10, 5.0}; // 错误!需要缩窄转型 193 | \end{lstlisting} 194 | 195 | 在这个例子中,编译器将会完全忽视掉前两个构造函数(注意到第二个构造函数的参数是完全匹配的),并且试图调用那个接受std::initializer\_list为参数的构造函数。而调用那个构造函数需要将int(10)和double(5.0)转型为bool。这两个转型都是缩窄转型(bool不能被其它值表示),而大括号初始化又阻止了缩窄转型,因此这个调用是非法的,代码无法通过编译。 196 | 197 | 只有当无法将std::initializer\_list中的值转型成正确的类型时,编译器才会将其他的重载构造函数作为大括号初始化的调用函数。例如,如果我们将std::initializer\_list改写成std::initializer\_list,此时其他的重载构造函数才会重新成为候选,因为编译器无法将int和bool转型为std::string: 198 | 199 | \begin{lstlisting} 200 | class Widget { 201 | public: 202 | Widget(int i, bool b); 203 | Widget(int i, double d); 204 | 205 | // std::initializer_list的元素类型为std::string 206 | Widget(std::initializer_list il); 207 | 208 | ... // 没有隐式转型函数 209 | 210 | }; 211 | 212 | Widget w1(10, true); // 使用小括号,调用第一个构造函数 213 | 214 | Widget w2{10, true}; // 使用大括号,但调用第一个构造函数 215 | 216 | Widget w3(10, 5.0); // 使用小括号,调用第二个构造函数 217 | 218 | Widget w4{10, 5.0}; // 使用大括号,但调用第二个构造函数 219 | \end{lstlisting} 220 | 221 | 现在我们就快结束大括号初始化和重载构造函数的讨论了,但还有一个极端情况需要说明。如果你用一个空的大括号试图去初始化一个对象,而它既提供默认构造函数,又提供std::initializer\_list为参数的构造函数,它将会调用哪一个?如果空的大括号表示没有参数,那么应该调用默认构造函数;如果它表示空的std::initializer\_list,那么就应该调用后一个构造函数。 222 | 223 | 解析规则告诉我们最终会调用默认构造函数。空的大括号表示没有参数。而不是空的std::initializer\_list: 224 | 225 | \begin{lstlisting} 226 | class Widget { 227 | public: 228 | Widget(); // 默认构造函数 229 | 230 | // std::initializer_list构造函数 231 | Widget(std::initializer_list il); 232 | 233 | ... // 没有隐式转型函数 234 | }; 235 | 236 | Widget w1; // 调用默认构造函数 237 | 238 | Widget w2{}; // 调用默认构造函数 239 | 240 | Widget w3(); // 令人苦恼的解析难题,这是一个函数声明! 241 | \end{lstlisting} 242 | 243 | 如果你想用空的std::initializer\_list调用参数为std::initializer\_list的构造函数,你需要将参数的周围再加上大括号或者小括号加以区分,用它作为构造函数的参数: 244 | 245 | \begin{lstlisting} 246 | // 调用参数为std::initializer_list的构造函数 247 | Widget w4({}); 248 | 249 | // 调用参数为std::initializer_list的构造函数 250 | Widget w5{{}}; 251 | \end{lstlisting} 252 | 253 | 此时此刻,在了解这么多关于大括号初始化,std::initializer\_list和重载构造函数的复杂规则后,你也许想知道实际编程的过程中遭遇这类问题的频繁程度。事实上会多得超出你的想象,因为std::vector就受到了这类问题的困扰。std::vector有一个非std::initializer\_list的构造函数接受两个参数,一个是容器的大小,一个是元素的初始值,但另一个std::initializer\_list构造函数则允许向对象传递初始值。因此如果你定义一个数值类型的std::vector,然后向这个对象传递两个参数,那么传递参数的方式将会极大的影响这个对象的值: 254 | 255 | \begin{lstlisting} 256 | // 调用参数为数值的构造函数:创建一个拥有10个元素,每个元素初始值为20的容器 257 | std::vector v1(10, 20); 258 | 259 | // 调用参数为std::initializer_list的构造函数:创建一个拥有两个元素的容器,元素值为10和20 260 | std::vector v2{10, 20}; 261 | \end{lstlisting} 262 | 263 | 让我们从std::vector和大括号、小括号以及重载构造函数的解析规则的细节中跳出来,在这个问题上有两个基本关注点值得讨论。第一,作为类的设计者,如果你的类包含了一个或多个接受std::initializer\_list为参数的构造函数,此时用户代码如果使用大括号初始化,将会忽略掉所有的非std::initializer\_list构造函数,只调用参数为std::initializer\_list的构造函数。因此你在设计构造函时,应该避免因大括号或小括号造成初始化结果不同的影响。换句话说,你应该意识到std::vector接口的设计错误,然后在设计类的时候避免这类问题。 264 | 265 | 另外一个隐含的问题是,如果你有一个之前不包含std::initializer\_list构造函数的类,在重构过程中添加了一个,那么你之前所有使用大括号初始化的代码可能会被重新解析,从调用普通的构造函数变成参数为std::initializer\_list的构造函数。当然,这一类问题在你向一类重载函数添加新函数的时候经常发生:那些调用旧函数的代码将会被解析成调用新函数。但它们有一个重要的区别:参数为std::initializer\_list的构造函数根本就不会和其他的非std::initializer\_list构造函数进行竞争,它几乎遮盖了其他所有的构造函数,除非无法进行类型转换。所以向类中添加这样的重载构造函数时一定要慎重考虑。 266 | 267 | 第二个教训是作为类的使用者,你必须很小心的在大括号和小括号之间取舍来作为初始化对象的方式。大部分开发者都会选择其中的一种作为默认方式,只有在必要的情况下才会用另一种方式。如果你喜欢大括号的广泛应用场景,阻止缩窄转型以及对C++解析语法问题的免疫,那么就选择大括号初始化,只是要弄明白在有些情况下小括号是必须的(比如给定大小和初始值来创建std::vector对象)。另一方面,那些希望与C++98保持语法一致,比且避免std::initializer\_list引起的auto类型推导问题,以及重载std::initializer\_list构造函数引起的函数调用问题的开发者则会倾向选择小括号初始化,只不过有的时候必须用到大括号(比如用特定的初始值来初始化)。这两种方法孰优孰劣目前并没有达成共识,因此我的建议是选择其中的一种然后坚持使用它。 268 | 269 | 如果你是模板的作者,那么大括号和小括号在创建对象的差异会特别令人沮丧,因为通常无法得知哪一种方式更应该使用。比如你想要创建一个对象,它可以是任意类型,也可以用任意参数来初始化。一番考虑后你写出这样的可变模板: 270 | 271 | \begin{lstlisting} 272 | // 描述这个对象的类型和参数 273 | template 274 | void doSomeWork(Ts&&... params) 275 | { 276 | create local T object from params... 277 | ... 278 | } 279 | \end{lstlisting} 280 | 281 | 有两种方式能够填充这段伪代码(查看条款25了解有关std::forward的信息): 282 | 283 | \begin{lstlisting} 284 | T localObject(std::forward(params)...); // 使用小括号 285 | 286 | T localObject{std::forward(params)...}; // 使用大括号 287 | \end{lstlisting} 288 | 289 | 考虑要调用的代码: 290 | 291 | \begin{lstlisting} 292 | std::vector v; 293 | ... 294 | doSomeWork>(10, 20); 295 | \end{lstlisting} 296 | 297 | 如果doSomeWork用小括号来创建localObject,那么结果是创建了一个有10个元素的std::vector。如果doSomeWork用大括号,那么结果是创建了一个有2个元素的std::vector。哪一种方式是正确的?doSomeWork的作者不知道,恐怕只有调用者自己知道。 298 | 299 | 这正是标准库中std::make\_unique和std::make\_shared面临的问题(查看条款21)。这两个函数通过在内部使用小括号,并且在文档中标明了它们的接口来解决这个问题。 300 | 301 | \begin{mdframed} 302 | 请记住: 303 | \begin{itemize} 304 | \item{大括号初始化是最为通用的初始化语法,他能够阻止缩窄转型并且避免C++的解析语法问题。} 305 | \item{在重载构造函数的选择中,大括号初始化总是会尽可能的选择参数为std::initializer\_list的构造函数,即使其它的构造函数有更好的匹配结果。} 306 | \item{一个因为选取大括号或小括号进行初始化从而导致巨大差异的最典型例子是:用两个参数来创建一个std::vector对象。} 307 | \item{在模板中选择用大括号或者小括号来创建对象是一个挑战。} 308 | \end{itemize} 309 | \end{mdframed} 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /EffectiveModernCppCN.log: -------------------------------------------------------------------------------- 1 | This is XeTeX, Version 3.14159265-2.6-0.99991 (TeX Live 2014) (preloaded format=xelatex 2015.3.28) 30 SEP 2015 10:19 2 | entering extended mode 3 | restricted \write18 enabled. 4 | file:line:error style messages enabled. 5 | %&-line parsing enabled. 6 | **EffectiveModernCppCN.tex 7 | (./EffectiveModernCppCN.tex 8 | LaTeX2e <2014/05/01> 9 | Babel <3.9l> and hyphenation patterns for 79 languages loaded. 10 | (/usr/local/texlive/2014/texmf-dist/tex/latex/base/book.cls 11 | Document Class: book 2014/09/29 v1.4h Standard LaTeX document class 12 | (/usr/local/texlive/2014/texmf-dist/tex/latex/base/bk10.clo 13 | File: bk10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) 14 | ) 15 | \c@part=\count80 16 | \c@chapter=\count81 17 | \c@section=\count82 18 | \c@subsection=\count83 19 | \c@subsubsection=\count84 20 | \c@paragraph=\count85 21 | \c@subparagraph=\count86 22 | \c@figure=\count87 23 | \c@table=\count88 24 | \abovecaptionskip=\skip41 25 | \belowcaptionskip=\skip42 26 | \bibindent=\dimen102 27 | ) 28 | (/usr/local/texlive/2014/texmf-dist/tex/latex/geometry/geometry.sty 29 | Package: geometry 2010/09/12 v5.6 Page Geometry 30 | 31 | (/usr/local/texlive/2014/texmf-dist/tex/latex/graphics/keyval.sty 32 | Package: keyval 2014/10/28 v1.15 key=value parser (DPC) 33 | \KV@toks@=\toks14 34 | ) 35 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/ifpdf.sty 36 | Package: ifpdf 2011/01/30 v2.3 Provides the ifpdf switch (HO) 37 | Package ifpdf Info: pdfTeX in PDF mode is not detected. 38 | ) 39 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/ifvtex.sty 40 | Package: ifvtex 2010/03/01 v1.5 Detect VTeX and its facilities (HO) 41 | Package ifvtex Info: VTeX not detected. 42 | ) 43 | (/usr/local/texlive/2014/texmf-dist/tex/generic/ifxetex/ifxetex.sty 44 | Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional 45 | ) 46 | \Gm@cnth=\count89 47 | \Gm@cntv=\count90 48 | \c@Gm@tempcnt=\count91 49 | \Gm@bindingoffset=\dimen103 50 | \Gm@wd@mp=\dimen104 51 | \Gm@odd@mp=\dimen105 52 | \Gm@even@mp=\dimen106 53 | \Gm@layoutwidth=\dimen107 54 | \Gm@layoutheight=\dimen108 55 | \Gm@layouthoffset=\dimen109 56 | \Gm@layoutvoffset=\dimen110 57 | \Gm@dimlist=\toks15 58 | ) 59 | (/usr/local/texlive/2014/texmf-dist/tex/latex/mdframed/mdframed.sty 60 | Package: mdframed 2013/07/01 1.9b: mdframed 61 | 62 | (/usr/local/texlive/2014/texmf-dist/tex/latex/oberdiek/kvoptions.sty 63 | Package: kvoptions 2011/06/30 v3.11 Key value format for package options (HO) 64 | 65 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/ltxcmds.sty 66 | Package: ltxcmds 2011/11/09 v1.22 LaTeX kernel commands for general use (HO) 67 | ) 68 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/kvsetkeys.sty 69 | Package: kvsetkeys 2012/04/25 v1.16 Key value parser (HO) 70 | 71 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/infwarerr.sty 72 | Package: infwarerr 2010/04/08 v1.3 Providing info/warning/error messages (HO) 73 | ) 74 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/etexcmds.sty 75 | Package: etexcmds 2011/02/16 v1.5 Avoid name clashes with e-TeX commands (HO) 76 | 77 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/ifluatex.sty 78 | Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO) 79 | Package ifluatex Info: LuaTeX not detected. 80 | ) 81 | Package etexcmds Info: Could not find \expanded. 82 | (etexcmds) That can mean that you are not using pdfTeX 1.50 or 83 | (etexcmds) that some package has redefined \expanded. 84 | (etexcmds) In the latter case, load this package earlier. 85 | ))) 86 | (/usr/local/texlive/2014/texmf-dist/tex/latex/l3packages/xparse/xparse.sty 87 | (/usr/local/texlive/2014/texmf-dist/tex/latex/l3kernel/expl3.sty 88 | Package: expl3 2015/03/01 v5547 L3 programming layer (loader) 89 | 90 | (/usr/local/texlive/2014/texmf-dist/tex/latex/l3kernel/expl3-code.tex 91 | Package: expl3 2015/03/01 v5547 L3 programming layer (code) 92 | L3 Module: l3bootstrap 2015/02/28 v5542 L3 Bootstrap code 93 | 94 | (/usr/local/texlive/2014/texmf-dist/tex/latex/etex-pkg/etex.sty 95 | Package: etex 2015/03/02 v2.1 eTeX basic definition package (PEB,DPC) 96 | \et@xins=\count92 97 | ) 98 | L3 Module: l3names 2015/02/24 v5535 L3 Namespace for primitives 99 | L3 Module: l3basics 2015/01/27 v5500 L3 Basic definitions 100 | L3 Module: l3expan 2014/11/27 v5472 L3 Argument expansion 101 | L3 Module: l3tl 2015/01/27 v5500 L3 Token lists 102 | L3 Module: l3str 2015/03/01 v5545 L3 Strings 103 | L3 Module: l3seq 2014/08/23 v5354 L3 Sequences and stacks 104 | L3 Module: l3int 2015/02/21 v5529 L3 Integers 105 | \c_max_int=\count93 106 | \l_tmpa_int=\count94 107 | \l_tmpb_int=\count95 108 | \g_tmpa_int=\count96 109 | \g_tmpb_int=\count97 110 | L3 Module: l3quark 2014/08/23 v5354 L3 Quarks 111 | L3 Module: l3prg 2014/08/23 v5354 L3 Control structures 112 | \g__prg_map_int=\count98 113 | L3 Module: l3clist 2014/08/23 v5354 L3 Comma separated lists 114 | L3 Module: l3token 2014/09/15 v5422 L3 Experimental token manipulation 115 | L3 Module: l3prop 2014/08/23 v5354 L3 Property lists 116 | L3 Module: l3msg 2015/02/26 v5537 L3 Messages 117 | L3 Module: l3file 2014/08/24 v5369 L3 File and I/O operations 118 | \l_iow_line_count_int=\count99 119 | \l__iow_target_count_int=\count100 120 | \l__iow_current_line_int=\count101 121 | \l__iow_current_word_int=\count102 122 | \l__iow_current_indentation_int=\count103 123 | L3 Module: l3skip 2014/08/23 v5354 L3 Dimensions and skips 124 | \c_zero_dim=\dimen111 125 | \c_max_dim=\dimen112 126 | \l_tmpa_dim=\dimen113 127 | \l_tmpb_dim=\dimen114 128 | \g_tmpa_dim=\dimen115 129 | \g_tmpb_dim=\dimen116 130 | \c_zero_skip=\skip43 131 | \c_max_skip=\skip44 132 | \l_tmpa_skip=\skip45 133 | \l_tmpb_skip=\skip46 134 | \g_tmpa_skip=\skip47 135 | \g_tmpb_skip=\skip48 136 | \c_zero_muskip=\muskip10 137 | \c_max_muskip=\muskip11 138 | \l_tmpa_muskip=\muskip12 139 | \l_tmpb_muskip=\muskip13 140 | \g_tmpa_muskip=\muskip14 141 | \g_tmpb_muskip=\muskip15 142 | L3 Module: l3keys 2015/01/27 v5500 L3 Key-value interfaces 143 | \g__keyval_level_int=\count104 144 | \l_keys_choice_int=\count105 145 | L3 Module: l3fp 2014/08/22 v5336 L3 Floating points 146 | \c__fp_leading_shift_int=\count106 147 | \c__fp_middle_shift_int=\count107 148 | \c__fp_trailing_shift_int=\count108 149 | \c__fp_big_leading_shift_int=\count109 150 | \c__fp_big_middle_shift_int=\count110 151 | \c__fp_big_trailing_shift_int=\count111 152 | \c__fp_Bigg_leading_shift_int=\count112 153 | \c__fp_Bigg_middle_shift_int=\count113 154 | \c__fp_Bigg_trailing_shift_int=\count114 155 | L3 Module: l3box 2014/08/23 v5354 L3 Experimental boxes 156 | \c_empty_box=\box26 157 | \l_tmpa_box=\box27 158 | \l_tmpb_box=\box28 159 | \g_tmpa_box=\box29 160 | \g_tmpb_box=\box30 161 | L3 Module: l3coffins 2014/08/23 v5354 L3 Coffin code layer 162 | \l__coffin_internal_box=\box31 163 | \l__coffin_internal_dim=\dimen117 164 | \l__coffin_offset_x_dim=\dimen118 165 | \l__coffin_offset_y_dim=\dimen119 166 | \l__coffin_x_dim=\dimen120 167 | \l__coffin_y_dim=\dimen121 168 | \l__coffin_x_prime_dim=\dimen122 169 | \l__coffin_y_prime_dim=\dimen123 170 | \c_empty_coffin=\box32 171 | \l__coffin_aligned_coffin=\box33 172 | \l__coffin_aligned_internal_coffin=\box34 173 | \l_tmpa_coffin=\box35 174 | \l_tmpb_coffin=\box36 175 | \l__coffin_display_coffin=\box37 176 | \l__coffin_display_coord_coffin=\box38 177 | \l__coffin_display_pole_coffin=\box39 178 | \l__coffin_display_offset_dim=\dimen124 179 | \l__coffin_display_x_dim=\dimen125 180 | \l__coffin_display_y_dim=\dimen126 181 | L3 Module: l3color 2014/08/23 v5354 L3 Experimental color support 182 | L3 Module: l3candidates 2015/03/01 v5544 L3 Experimental additions to l3kernel 183 | \l__box_top_dim=\dimen127 184 | \l__box_bottom_dim=\dimen128 185 | \l__box_left_dim=\dimen129 186 | \l__box_right_dim=\dimen130 187 | \l__box_top_new_dim=\dimen131 188 | \l__box_bottom_new_dim=\dimen132 189 | \l__box_left_new_dim=\dimen133 190 | \l__box_right_new_dim=\dimen134 191 | \l__box_internal_box=\box40 192 | \l__coffin_bounding_shift_dim=\dimen135 193 | \l__coffin_left_corner_dim=\dimen136 194 | \l__coffin_right_corner_dim=\dimen137 195 | \l__coffin_bottom_corner_dim=\dimen138 196 | \l__coffin_top_corner_dim=\dimen139 197 | \l__coffin_scaled_total_height_dim=\dimen140 198 | \l__coffin_scaled_width_dim=\dimen141 199 | ) 200 | (/usr/local/texlive/2014/texmf-dist/tex/latex/l3kernel/l3unicode-data.def 201 | File: l3unicode-data.def 2015/03/01 v5544 L3 Unicode data 202 | ) 203 | (/usr/local/texlive/2014/texmf-dist/tex/latex/l3kernel/l3xdvipdfmx.def 204 | File: l3xdvidpfmx.def 2015/03/01 v5544 L3 Experimental driver: xdvipdfmx 205 | )) 206 | Package: xparse 2014/11/25 v5471 L3 Experimental document command parser 207 | \l__xparse_current_arg_int=\count115 208 | \l__xparse_m_args_int=\count116 209 | \l__xparse_mandatory_args_int=\count117 210 | \l__xparse_processor_int=\count118 211 | \l__xparse_v_nesting_int=\count119 212 | ) 213 | (/usr/local/texlive/2014/texmf-dist/tex/latex/etoolbox/etoolbox.sty 214 | Package: etoolbox 2015/03/19 v2.1d e-TeX tools for LaTeX (JAW) 215 | \etb@tempcnta=\count120 216 | ) 217 | (/usr/local/texlive/2014/texmf-dist/tex/latex/oberdiek/zref-abspage.sty 218 | Package: zref-abspage 2012/04/04 v2.24 Module abspage for zref (HO) 219 | 220 | (/usr/local/texlive/2014/texmf-dist/tex/latex/oberdiek/zref-base.sty 221 | Package: zref-base 2012/04/04 v2.24 Module base for zref (HO) 222 | 223 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/kvdefinekeys.sty 224 | Package: kvdefinekeys 2011/04/07 v1.3 Define keys (HO) 225 | ) 226 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty 227 | Package: pdftexcmds 2011/11/29 v0.20 Utility functions of pdfTeX for LuaTeX (HO 228 | ) 229 | Package pdftexcmds Info: LuaTeX not detected. 230 | Package pdftexcmds Info: pdfTeX >= 1.30 not detected. 231 | Package pdftexcmds Info: \pdf@primitive is available. 232 | Package pdftexcmds Info: \pdf@ifprimitive is available. 233 | Package pdftexcmds Info: \pdfdraftmode not found. 234 | ) 235 | (/usr/local/texlive/2014/texmf-dist/tex/latex/oberdiek/auxhook.sty 236 | Package: auxhook 2011/03/04 v1.3 Hooks for auxiliary files (HO) 237 | ) 238 | Package zref Info: New property list: main on input line 759. 239 | Package zref Info: New property: default on input line 760. 240 | Package zref Info: New property: page on input line 761. 241 | ) 242 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/atbegshi.sty 243 | Package: atbegshi 2011/10/05 v1.16 At begin shipout hook (HO) 244 | ) 245 | \c@abspage=\count121 246 | Package zref Info: New property: abspage on input line 62. 247 | ) 248 | (/usr/local/texlive/2014/texmf-dist/tex/latex/needspace/needspace.sty 249 | Package: needspace 2010/09/12 v1.3d reserve vertical space 250 | ) 251 | (/usr/local/texlive/2014/texmf-dist/tex/latex/graphics/color.sty 252 | Package: color 2014/10/28 v1.1a Standard LaTeX Color (DPC) 253 | 254 | (/usr/local/texlive/2014/texmf-dist/tex/latex/latexconfig/color.cfg 255 | File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive 256 | ) 257 | Package color Info: Driver file: xetex.def on input line 137. 258 | 259 | (/usr/local/texlive/2014/texmf-dist/tex/xelatex/xetex-def/xetex.def 260 | File: xetex.def 2014/07/25 v4.03 LaTeX color/graphics driver for XeTeX (RRM/JK) 261 | 262 | )) 263 | \mdf@templength=\skip49 264 | \c@mdf@globalstyle@cnt=\count122 265 | \mdf@skipabove@length=\skip50 266 | \mdf@skipbelow@length=\skip51 267 | \mdf@leftmargin@length=\skip52 268 | \mdf@rightmargin@length=\skip53 269 | \mdf@innerleftmargin@length=\skip54 270 | \mdf@innerrightmargin@length=\skip55 271 | \mdf@innertopmargin@length=\skip56 272 | \mdf@innerbottommargin@length=\skip57 273 | \mdf@splittopskip@length=\skip58 274 | \mdf@splitbottomskip@length=\skip59 275 | \mdf@outermargin@length=\skip60 276 | \mdf@innermargin@length=\skip61 277 | \mdf@linewidth@length=\skip62 278 | \mdf@innerlinewidth@length=\skip63 279 | \mdf@middlelinewidth@length=\skip64 280 | \mdf@outerlinewidth@length=\skip65 281 | \mdf@roundcorner@length=\skip66 282 | \mdf@footenotedistance@length=\skip67 283 | \mdf@userdefinedwidth@length=\skip68 284 | \mdf@needspace@length=\skip69 285 | \mdf@frametitleaboveskip@length=\skip70 286 | \mdf@frametitlebelowskip@length=\skip71 287 | \mdf@frametitlerulewidth@length=\skip72 288 | \mdf@frametitleleftmargin@length=\skip73 289 | \mdf@frametitlerightmargin@length=\skip74 290 | \mdf@shadowsize@length=\skip75 291 | \mdf@extratopheight@length=\skip76 292 | \mdf@subtitleabovelinewidth@length=\skip77 293 | \mdf@subtitlebelowlinewidth@length=\skip78 294 | \mdf@subtitleaboveskip@length=\skip79 295 | \mdf@subtitlebelowskip@length=\skip80 296 | \mdf@subtitleinneraboveskip@length=\skip81 297 | \mdf@subtitleinnerbelowskip@length=\skip82 298 | \mdf@subsubtitleabovelinewidth@length=\skip83 299 | \mdf@subsubtitlebelowlinewidth@length=\skip84 300 | \mdf@subsubtitleaboveskip@length=\skip85 301 | \mdf@subsubtitlebelowskip@length=\skip86 302 | \mdf@subsubtitleinneraboveskip@length=\skip87 303 | \mdf@subsubtitleinnerbelowskip@length=\skip88 304 | 305 | (/usr/local/texlive/2014/texmf-dist/tex/latex/mdframed/md-frame-0.mdf 306 | File: md-frame-0.mdf 2013/07/01\ 1.9b: md-frame-0 307 | ) 308 | \mdf@frametitlebox=\box41 309 | \mdf@footnotebox=\box42 310 | \mdf@splitbox@one=\box43 311 | \mdf@splitbox@two=\box44 312 | \mdf@splitbox@save=\box45 313 | \mdfsplitboxwidth=\skip89 314 | \mdfsplitboxtotalwidth=\skip90 315 | \mdfsplitboxheight=\skip91 316 | \mdfsplitboxdepth=\skip92 317 | \mdfsplitboxtotalheight=\skip93 318 | \mdfframetitleboxwidth=\skip94 319 | \mdfframetitleboxtotalwidth=\skip95 320 | \mdfframetitleboxheight=\skip96 321 | \mdfframetitleboxdepth=\skip97 322 | \mdfframetitleboxtotalheight=\skip98 323 | \mdffootnoteboxwidth=\skip99 324 | \mdffootnoteboxtotalwidth=\skip100 325 | \mdffootnoteboxheight=\skip101 326 | \mdffootnoteboxdepth=\skip102 327 | \mdffootnoteboxtotalheight=\skip103 328 | \mdftotallinewidth=\skip104 329 | \mdfboundingboxwidth=\skip105 330 | \mdfboundingboxtotalwidth=\skip106 331 | \mdfboundingboxheight=\skip107 332 | \mdfboundingboxdepth=\skip108 333 | \mdfboundingboxtotalheight=\skip109 334 | \mdf@freevspace@length=\skip110 335 | \mdf@horizontalwidthofbox@length=\skip111 336 | \mdf@verticalmarginwhole@length=\skip112 337 | \mdf@horizontalspaceofbox=\skip113 338 | \mdfsubtitleheight=\skip114 339 | \mdfsubsubtitleheight=\skip115 340 | \c@mdfcountframes=\count123 341 | 342 | ****** mdframed patching \endmdf@trivlist 343 | 344 | ****** -- success****** 345 | 346 | ................................................. 347 | . LaTeX info: "xparse/define-command" 348 | . 349 | . Defining command \newmdtheoremenv with sig. 'O{} m o m o ' on line 601. 350 | ................................................. 351 | ................................................. 352 | . LaTeX info: "xparse/define-command" 353 | . 354 | . Defining command \mdtheorem with sig. ' O{} m o m o ' on line 701. 355 | ................................................. 356 | \mdf@envdepth=\count124 357 | \c@mdf@env@i=\count125 358 | \c@mdf@env@ii=\count126 359 | \c@mdf@zref@counter=\count127 360 | Package zref Info: New property: mdf@pagevalue on input line 895. 361 | ) 362 | (/usr/local/texlive/2014/texmf-dist/tex/latex/lipsum/lipsum.sty 363 | Package: lipsum 2014/07/27 v1.3 150 paragraphs of Lorem Ipsum dummy text 364 | \c@lips@count=\count128 365 | ) 366 | (/usr/local/texlive/2014/texmf-dist/tex/latex/tools/indentfirst.sty 367 | Package: indentfirst 1995/11/23 v1.03 Indent first paragraph (DPC) 368 | ) 369 | (/usr/local/texlive/2014/texmf-dist/tex/latex/hyperref/hyperref.sty 370 | Package: hyperref 2012/11/06 v6.83m Hypertext links for LaTeX 371 | 372 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty 373 | Package: hobsub-hyperref 2012/05/28 v1.13 Bundle oberdiek, subset hyperref (HO) 374 | 375 | 376 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty 377 | Package: hobsub-generic 2012/05/28 v1.13 Bundle oberdiek, subset generic (HO) 378 | Package: hobsub 2012/05/28 v1.13 Construct package bundles (HO) 379 | Package hobsub Info: Skipping package `infwarerr' (already loaded). 380 | Package hobsub Info: Skipping package `ltxcmds' (already loaded). 381 | Package hobsub Info: Skipping package `ifluatex' (already loaded). 382 | Package hobsub Info: Skipping package `ifvtex' (already loaded). 383 | Package: intcalc 2007/09/27 v1.1 Expandable calculations with integers (HO) 384 | Package hobsub Info: Skipping package `ifpdf' (already loaded). 385 | Package hobsub Info: Skipping package `etexcmds' (already loaded). 386 | Package hobsub Info: Skipping package `kvsetkeys' (already loaded). 387 | Package hobsub Info: Skipping package `kvdefinekeys' (already loaded). 388 | Package hobsub Info: Skipping package `pdftexcmds' (already loaded). 389 | Package: pdfescape 2011/11/25 v1.13 Implements pdfTeX's escape features (HO) 390 | Package: bigintcalc 2012/04/08 v1.3 Expandable calculations on big integers (HO 391 | ) 392 | Package: bitset 2011/01/30 v1.1 Handle bit-vector datatype (HO) 393 | Package: uniquecounter 2011/01/30 v1.2 Provide unlimited unique counter (HO) 394 | ) 395 | Package hobsub Info: Skipping package `hobsub' (already loaded). 396 | Package: letltxmacro 2010/09/02 v1.4 Let assignment for LaTeX macros (HO) 397 | Package: hopatch 2012/05/28 v1.2 Wrapper for package hooks (HO) 398 | Package: xcolor-patch 2011/01/30 xcolor patch 399 | Package: atveryend 2011/06/30 v1.8 Hooks at the very end of document (HO) 400 | Package hobsub Info: Skipping package `atbegshi' (already loaded). 401 | Package: refcount 2011/10/16 v3.4 Data extraction from label references (HO) 402 | Package: hycolor 2011/01/30 v1.7 Color options for hyperref/bookmark (HO) 403 | ) 404 | \@linkdim=\dimen142 405 | \Hy@linkcounter=\count129 406 | \Hy@pagecounter=\count130 407 | 408 | (/usr/local/texlive/2014/texmf-dist/tex/latex/hyperref/pd1enc.def 409 | File: pd1enc.def 2012/11/06 v6.83m Hyperref: PDFDocEncoding definition (HO) 410 | ) 411 | \Hy@SavedSpaceFactor=\count131 412 | 413 | (/usr/local/texlive/2014/texmf-dist/tex/latex/latexconfig/hyperref.cfg 414 | File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive 415 | ) 416 | Package hyperref Info: Option `colorlinks' set `true' on input line 4319. 417 | Package hyperref Info: Hyper figures OFF on input line 4443. 418 | Package hyperref Info: Link nesting OFF on input line 4448. 419 | Package hyperref Info: Hyper index ON on input line 4451. 420 | Package hyperref Info: Plain pages OFF on input line 4458. 421 | Package hyperref Info: Backreferencing OFF on input line 4463. 422 | Package hyperref Info: Implicit mode ON; LaTeX internals redefined. 423 | Package hyperref Info: Bookmarks ON on input line 4688. 424 | \c@Hy@tempcnt=\count132 425 | 426 | (/usr/local/texlive/2014/texmf-dist/tex/latex/url/url.sty 427 | \Urlmuskip=\muskip16 428 | Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. 429 | ) 430 | LaTeX Info: Redefining \url on input line 5041. 431 | \XeTeXLinkMargin=\dimen143 432 | \Fld@menulength=\count133 433 | \Field@Width=\dimen144 434 | \Fld@charsize=\dimen145 435 | Package hyperref Info: Hyper figures OFF on input line 6295. 436 | Package hyperref Info: Link nesting OFF on input line 6300. 437 | Package hyperref Info: Hyper index ON on input line 6303. 438 | Package hyperref Info: backreferencing OFF on input line 6310. 439 | Package hyperref Info: Link coloring ON on input line 6313. 440 | Package hyperref Info: Link coloring with OCG OFF on input line 6320. 441 | Package hyperref Info: PDF/A mode OFF on input line 6325. 442 | LaTeX Info: Redefining \ref on input line 6365. 443 | LaTeX Info: Redefining \pageref on input line 6369. 444 | \Hy@abspage=\count134 445 | \c@Item=\count135 446 | \c@Hfootnote=\count136 447 | ) 448 | 449 | Package hyperref Message: Driver (autodetected): hxetex. 450 | 451 | (/usr/local/texlive/2014/texmf-dist/tex/latex/hyperref/hxetex.def 452 | File: hxetex.def 2012/11/06 v6.83m Hyperref driver for XeTeX 453 | 454 | (/usr/local/texlive/2014/texmf-dist/tex/latex/hyperref/puenc.def 455 | File: puenc.def 2012/11/06 v6.83m Hyperref: PDF Unicode definition (HO) 456 | ) 457 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/stringenc.sty 458 | Package: stringenc 2011/12/02 v1.10 Convert strings between diff. encodings (HO 459 | ) 460 | ) 461 | \pdfm@box=\box46 462 | \c@Hy@AnnotLevel=\count137 463 | \HyField@AnnotCount=\count138 464 | \Fld@listcount=\count139 465 | \c@bookmark@seq@number=\count140 466 | 467 | (/usr/local/texlive/2014/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty 468 | Package: rerunfilecheck 2011/04/15 v1.7 Rerun checks for auxiliary files (HO) 469 | Package rerunfilecheck Info: Feature \pdfmdfivesum is not available 470 | (rerunfilecheck) (e.g. pdfTeX or LuaTeX with package `pdftexcmds'). 471 | 472 | (rerunfilecheck) Therefore file contents cannot be checked efficien 473 | tly 474 | (rerunfilecheck) and the loading of the package is aborted. 475 | ) 476 | \Hy@SectionHShift=\skip116 477 | ) 478 | (/usr/local/texlive/2014/texmf-dist/tex/latex/listings/listings.sty 479 | \lst@mode=\count141 480 | \lst@gtempboxa=\box47 481 | \lst@token=\toks16 482 | \lst@length=\count142 483 | \lst@currlwidth=\dimen146 484 | \lst@column=\count143 485 | \lst@pos=\count144 486 | \lst@lostspace=\dimen147 487 | \lst@width=\dimen148 488 | \lst@newlines=\count145 489 | \lst@lineno=\count146 490 | \lst@maxwidth=\dimen149 491 | 492 | (/usr/local/texlive/2014/texmf-dist/tex/latex/listings/lstmisc.sty 493 | File: lstmisc.sty 2014/09/06 1.5e (Carsten Heinz) 494 | \c@lstnumber=\count147 495 | \lst@skipnumbers=\count148 496 | \lst@framebox=\box48 497 | ) 498 | (/usr/local/texlive/2014/texmf-dist/tex/latex/listings/listings.cfg 499 | File: listings.cfg 2014/09/06 1.5e listings configuration 500 | )) 501 | Package: listings 2014/09/06 1.5e (Carsten Heinz) 502 | 503 | (/usr/local/texlive/2014/texmf-dist/tex/latex/psnfss/courier.sty 504 | Package: courier 2005/04/12 PSNFSS-v9.2a (WaS) 505 | ) 506 | (/usr/local/texlive/2014/texmf-dist/tex/latex/lm/lmodern.sty 507 | Package: lmodern 2009/10/30 v1.6 Latin Modern Fonts 508 | LaTeX Font Info: Overwriting symbol font `operators' in version `normal' 509 | (Font) OT1/cmr/m/n --> OT1/lmr/m/n on input line 22. 510 | LaTeX Font Info: Overwriting symbol font `letters' in version `normal' 511 | (Font) OML/cmm/m/it --> OML/lmm/m/it on input line 23. 512 | LaTeX Font Info: Overwriting symbol font `symbols' in version `normal' 513 | (Font) OMS/cmsy/m/n --> OMS/lmsy/m/n on input line 24. 514 | LaTeX Font Info: Overwriting symbol font `largesymbols' in version `normal' 515 | (Font) OMX/cmex/m/n --> OMX/lmex/m/n on input line 25. 516 | LaTeX Font Info: Overwriting symbol font `operators' in version `bold' 517 | (Font) OT1/cmr/bx/n --> OT1/lmr/bx/n on input line 26. 518 | LaTeX Font Info: Overwriting symbol font `letters' in version `bold' 519 | (Font) OML/cmm/b/it --> OML/lmm/b/it on input line 27. 520 | LaTeX Font Info: Overwriting symbol font `symbols' in version `bold' 521 | (Font) OMS/cmsy/b/n --> OMS/lmsy/b/n on input line 28. 522 | LaTeX Font Info: Overwriting symbol font `largesymbols' in version `bold' 523 | (Font) OMX/cmex/m/n --> OMX/lmex/m/n on input line 29. 524 | LaTeX Font Info: Overwriting math alphabet `\mathbf' in version `normal' 525 | (Font) OT1/cmr/bx/n --> OT1/lmr/bx/n on input line 31. 526 | LaTeX Font Info: Overwriting math alphabet `\mathsf' in version `normal' 527 | (Font) OT1/cmss/m/n --> OT1/lmss/m/n on input line 32. 528 | LaTeX Font Info: Overwriting math alphabet `\mathit' in version `normal' 529 | (Font) OT1/cmr/m/it --> OT1/lmr/m/it on input line 33. 530 | LaTeX Font Info: Overwriting math alphabet `\mathtt' in version `normal' 531 | (Font) OT1/cmtt/m/n --> OT1/lmtt/m/n on input line 34. 532 | LaTeX Font Info: Overwriting math alphabet `\mathbf' in version `bold' 533 | (Font) OT1/cmr/bx/n --> OT1/lmr/bx/n on input line 35. 534 | LaTeX Font Info: Overwriting math alphabet `\mathsf' in version `bold' 535 | (Font) OT1/cmss/bx/n --> OT1/lmss/bx/n on input line 36. 536 | LaTeX Font Info: Overwriting math alphabet `\mathit' in version `bold' 537 | (Font) OT1/cmr/bx/it --> OT1/lmr/bx/it on input line 37. 538 | LaTeX Font Info: Overwriting math alphabet `\mathtt' in version `bold' 539 | (Font) OT1/cmtt/m/n --> OT1/lmtt/m/n on input line 38. 540 | ) 541 | (/usr/local/texlive/2014/texmf-dist/tex/latex/listings/lstlang1.sty 542 | File: lstlang1.sty 2014/09/06 1.5e listings language file 543 | ) 544 | (/usr/local/texlive/2014/texmf-dist/tex/latex/listings/lstlang1.sty 545 | File: lstlang1.sty 2014/09/06 1.5e listings language file 546 | ) 547 | (/usr/local/texlive/2014/texmf-dist/tex/latex/listings/lstmisc.sty 548 | File: lstmisc.sty 2014/09/06 1.5e (Carsten Heinz) 549 | ) 550 | (/usr/local/texlive/2014/texmf-dist/tex/xelatex/xecjk/xeCJK.sty 551 | Package: xeCJK 2014/12/26 v3.3.0 Typesetting CJK scripts with XeLaTeX 552 | 553 | (/usr/local/texlive/2014/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.st 554 | y 555 | Package: xtemplate 2014/11/25 v5471 L3 Experimental prototype document function 556 | s 557 | \l__xtemplate_tmp_dim=\dimen150 558 | \l__xtemplate_tmp_int=\count149 559 | \l__xtemplate_tmp_muskip=\muskip17 560 | \l__xtemplate_tmp_skip=\skip117 561 | Variant \prop_get:NoNTF already defined; not changing it on line 106 562 | Variant \prop_get:NoNT already defined; not changing it on line 107 563 | Variant \prop_get:NoNF already defined; not changing it on line 108 564 | ) 565 | (/usr/local/texlive/2014/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty 566 | Package: l3keys2e 2014/11/25 v5471 LaTeX2e option processing using LaTeX3 keys 567 | ) 568 | \l__xeCJK_tmp_int=\count150 569 | \l__xeCJK_tmp_box=\box49 570 | \l__xeCJK_tmp_dim=\dimen151 571 | \l__xeCJK_tmp_skip=\skip118 572 | ................................................. 573 | . LaTeX info: "xparse/define-command" 574 | . 575 | . Defining command \xeCJKShipoutHook with sig. '' on line 153. 576 | ................................................. 577 | \g__xeCJK_spacefactor_int=\count151 578 | \l__xeCJK_begin_int=\count152 579 | \l__xeCJK_end_int=\count153 580 | ................................................. 581 | . LaTeX info: "xparse/define-command" 582 | . 583 | . Defining command \makexeCJKactive with sig. '' on line 371. 584 | ................................................. 585 | ................................................. 586 | . LaTeX info: "xparse/define-command" 587 | . 588 | . Defining command \makexeCJKinactive with sig. '' on line 372. 589 | ................................................. 590 | \c__xeCJK_HalfLeft_class_int=\XeTeXintercharclass4 591 | \c__xeCJK_HalfRight_class_int=\XeTeXintercharclass5 592 | \c__xeCJK_NormalSpace_class_int=\XeTeXintercharclass6 593 | \c__xeCJK_IVS_class_int=\XeTeXintercharclass7 594 | \c__xeCJK_HangulJamo_class_int=\XeTeXintercharclass8 595 | ................................................. 596 | . LaTeX info: "xparse/define-command" 597 | . 598 | . Defining command \xeCJKDeclareCharClass with sig. 's>{\TrimSpaces }mm' on 599 | . line 530. 600 | ................................................. 601 | ................................................. 602 | . LaTeX info: "xparse/define-command" 603 | . 604 | . Defining command \__xeCJK_set_char_class_aux:Nnw with sig. 605 | . 'm>{\SplitArgument {1}{->}}m' on line 547. 606 | ................................................. 607 | ................................................. 608 | . LaTeX info: "xparse/define-command" 609 | . 610 | . Defining command \normalspacedchars with sig. 'm' on line 589. 611 | ................................................. 612 | ................................................. 613 | . LaTeX info: "xparse/define-command" 614 | . 615 | . Defining command \xeCJKResetPunctClass with sig. '' on line 596. 616 | ................................................. 617 | ................................................. 618 | . LaTeX info: "xparse/define-command" 619 | . 620 | . Defining command \xeCJKResetCharClass with sig. '' on line 604. 621 | ................................................. 622 | \g__xeCJK_node_int=\count154 623 | \c__xeCJK_CJK_node_dim=\dimen152 624 | \c__xeCJK_CJK-space_node_dim=\dimen153 625 | \c__xeCJK_default_node_dim=\dimen154 626 | \c__xeCJK_default-space_node_dim=\dimen155 627 | \c__xeCJK_CJK-nobreak_node_dim=\dimen156 628 | \c__xeCJK_normalspace_node_dim=\dimen157 629 | \l__xeCJK_ccglue_skip=\skip119 630 | \l__xeCJK_ecglue_skip=\skip120 631 | ................................................. 632 | . LaTeX info: "xparse/define-command" 633 | . 634 | . Defining command \xeCJKnobreak with sig. '' on line 1376. 635 | ................................................. 636 | ................................................. 637 | . LaTeX info: "xparse/define-command" 638 | . 639 | . Defining command \xeCJKDeclareSubCJKBlock with sig. 's>{\TrimSpaces 640 | . }m>{\TrimSpaces }m' on line 1565. 641 | ................................................. 642 | ................................................. 643 | . LaTeX info: "xparse/define-command" 644 | . 645 | . Defining command \xeCJKCancelSubCJKBlock with sig. 'sm' on line 1576. 646 | ................................................. 647 | ................................................. 648 | . LaTeX info: "xparse/define-command" 649 | . 650 | . Defining command \xeCJKRestoreSubCJKBlock with sig. 'sm' on line 1585. 651 | ................................................. 652 | ................................................. 653 | . LaTeX info: "xparse/define-command" 654 | . 655 | . Defining command \xeCJKsetwidth with sig. 'smm' on line 1683. 656 | ................................................. 657 | ................................................. 658 | . LaTeX info: "xparse/define-command" 659 | . 660 | . Defining command \xeCJKsetkern with sig. 'mmm' on line 1687. 661 | ................................................. 662 | ................................................. 663 | . xtemplate info: "declare-object-type" 664 | . 665 | . Declaring object type 'xeCJK/punctuation' taking \c_zero argument(s) on 666 | . line 1788. 667 | ................................................. 668 | \l__xeCJK_fixed_punct_width_dim=\dimen158 669 | \l__xeCJK_mixed_punct_width_dim=\dimen159 670 | \l__xeCJK_middle_punct_width_dim=\dimen160 671 | \l__xeCJK_fixed_margin_width_dim=\dimen161 672 | \l__xeCJK_mixed_margin_width_dim=\dimen162 673 | \l__xeCJK_middle_margin_width_dim=\dimen163 674 | \l__xeCJK_bound_punct_width_dim=\dimen164 675 | \l__xeCJK_bound_margin_width_dim=\dimen165 676 | \l__xeCJK_margin_minimum_dim=\dimen166 677 | \l__xeCJK_kerning_total_width_dim=\dimen167 678 | \l__xeCJK_same_align_margin_dim=\dimen168 679 | \l__xeCJK_different_align_margin_dim=\dimen169 680 | \l__xeCJK_kerning_margin_width_dim=\dimen170 681 | \l__xeCJK_kerning_margin_minimum_dim=\dimen171 682 | \l__xeCJK_bound_dim=\dimen172 683 | \l__xeCJK_reverse_bound_dim=\dimen173 684 | ................................................. 685 | . LaTeX info: "xparse/define-command" 686 | . 687 | . Defining command \xeCJKDeclarePunctStyle with sig. '>{\TrimSpaces }mm' on 688 | . line 2273. 689 | ................................................. 690 | ................................................. 691 | . LaTeX info: "xparse/define-command" 692 | . 693 | . Defining command \xeCJKEditPunctStyle with sig. '>{\TrimSpaces }mm' on line 694 | . 2286. 695 | ................................................. 696 | ................................................. 697 | . LaTeX info: "xparse/define-command" 698 | . 699 | . Defining command \setCJKfallbackfamilyfont with sig. 'mO{}m' on line 2374. 700 | ................................................. 701 | \g__xeCJK_family_int=\count155 702 | ................................................. 703 | . LaTeX info: "xparse/define-command" 704 | . 705 | . Defining command \CJKfamily with sig. 't+t-m' on line 2798. 706 | ................................................. 707 | ................................................. 708 | . LaTeX info: "xparse/define-command" 709 | . 710 | . Defining command \__xeCJK_gobble_CJKfamily:wn with sig. 't+t-m' on line 711 | . 2812. 712 | ................................................. 713 | ................................................. 714 | . LaTeX info: "xparse/define-command" 715 | . 716 | . Defining command \setCJKmainfont with sig. 'O{}m' on line 2862. 717 | ................................................. 718 | ................................................. 719 | . LaTeX info: "xparse/define-command" 720 | . 721 | . Defining command \setCJKsansfont with sig. 'O{}m' on line 2868. 722 | ................................................. 723 | ................................................. 724 | . LaTeX info: "xparse/define-command" 725 | . 726 | . Defining command \setCJKmonofont with sig. 'O{}m' on line 2873. 727 | ................................................. 728 | ................................................. 729 | . LaTeX info: "xparse/define-command" 730 | . 731 | . Defining command \setCJKfamilyfont with sig. 'mO{}m' on line 2880. 732 | ................................................. 733 | ................................................. 734 | . LaTeX info: "xparse/define-command" 735 | . 736 | . Defining command \newCJKfontfamily with sig. 'omO{}m' on line 2886. 737 | ................................................. 738 | ................................................. 739 | . LaTeX info: "xparse/define-command" 740 | . 741 | . Defining command \CJKfontspec with sig. 'O{}m' on line 2891. 742 | ................................................. 743 | ................................................. 744 | . LaTeX info: "xparse/define-command" 745 | . 746 | . Defining command \defaultCJKfontfeatures with sig. 'm' on line 2914. 747 | ................................................. 748 | ................................................. 749 | . LaTeX info: "xparse/define-command" 750 | . 751 | . Defining command \addCJKfontfeatures with sig. 'sO{}m' on line 2920. 752 | ................................................. 753 | ................................................. 754 | . LaTeX info: "xparse/define-command" 755 | . 756 | . Defining command \setCJKmathfont with sig. 'O{}m' on line 3089. 757 | ................................................. 758 | \l__xeCJK_verb_case_int=\count156 759 | ................................................. 760 | . LaTeX info: "xparse/define-command" 761 | . 762 | . Defining command \xeCJKVerbAddon with sig. '' on line 3242. 763 | ................................................. 764 | ................................................. 765 | . LaTeX info: "xparse/define-command" 766 | . 767 | . Defining command \xeCJKOffVerbAddon with sig. '' on line 3246. 768 | ................................................. 769 | \l__xeCJK_verb_exspace_skip=\skip121 770 | (/usr/local/texlive/2014/texmf-dist/tex/latex/fontspec/fontspec.sty 771 | Package: fontspec 2015/03/14 v2.4c Font selection for XeLaTeX and LuaLaTeX 772 | \l_fontspec_script_int=\count157 773 | \l_fontspec_language_int=\count158 774 | \l_fontspec_strnum_int=\count159 775 | \l__fontspec_tmpa_dim=\dimen174 776 | \l__fontspec_tmpb_dim=\dimen175 777 | \l__fontspec_tmpc_dim=\dimen176 778 | Variant \tl_gset:cV already defined; not changing it on line 71 779 | 780 | (/usr/local/texlive/2014/texmf-dist/tex/latex/fontspec/fontspec-patches.sty 781 | Package: fontspec-patches 2015/03/14 v2.4c Font selection for XeLaTeX and LuaLa 782 | TeX 783 | LaTeX Info: Redefining \em on input line 49. 784 | LaTeX Info: Redefining \emph on input line 57. 785 | LaTeX Info: Redefining \- on input line 60. 786 | ................................................. 787 | . LaTeX info: "xparse/redefine-command" 788 | . 789 | . Redefining command \oldstylenums with sig. 'm' on line 155. 790 | ................................................. 791 | ................................................. 792 | . LaTeX info: "xparse/define-command" 793 | . 794 | . Defining command \liningnums with sig. 'm' on line 159. 795 | ................................................. 796 | ) 797 | (/usr/local/texlive/2014/texmf-dist/tex/latex/fontspec/fontspec-xetex.sty 798 | Package: fontspec-xetex 2015/03/14 v2.4c Font selection for XeLaTeX and LuaLaTe 799 | X 800 | 801 | (/usr/local/texlive/2014/texmf-dist/tex/latex/base/fontenc.sty 802 | Package: fontenc 2005/09/27 v1.99g Standard LaTeX package 803 | 804 | (/usr/local/texlive/2014/texmf-dist/tex/latex/euenc/eu1enc.def 805 | File: eu1enc.def 2010/05/27 v0.1h Experimental Unicode font encodings 806 | ) 807 | LaTeX Font Info: Try loading font information for EU1+lmr on input line 100. 808 | 809 | 810 | (/usr/local/texlive/2014/texmf-dist/tex/latex/euenc/eu1lmr.fd 811 | File: eu1lmr.fd 2009/10/30 v1.6 Font defs for Latin Modern 812 | )) 813 | (/usr/local/texlive/2014/texmf-dist/tex/xelatex/xunicode/xunicode.sty 814 | File: xunicode.sty 2011/09/09 v0.981 provides access to latin accents and many 815 | other characters in Unicode lower plane 816 | 817 | (/usr/local/texlive/2014/texmf-dist/tex/latex/tipa/t3enc.def 818 | File: t3enc.def 2001/12/31 T3 encoding 819 | LaTeX Font Info: Try loading font information for EU1+lmss on input line 357 820 | . 821 | 822 | (/usr/local/texlive/2014/texmf-dist/tex/latex/euenc/eu1lmss.fd 823 | File: eu1lmss.fd 2009/10/30 v1.6 Font defs for Latin Modern 824 | )) 825 | \tipaTiiicode=\count160 826 | \tipasavetokens=\toks17 827 | \tipachecktokens=\toks18 828 | 829 | (/usr/local/texlive/2014/texmf-dist/tex/latex/graphics/graphicx.sty 830 | Package: graphicx 2014/10/28 v1.0g Enhanced LaTeX Graphics (DPC,SPQR) 831 | 832 | (/usr/local/texlive/2014/texmf-dist/tex/latex/graphics/graphics.sty 833 | Package: graphics 2014/10/28 v1.0p Standard LaTeX Graphics (DPC,SPQR) 834 | 835 | (/usr/local/texlive/2014/texmf-dist/tex/latex/graphics/trig.sty 836 | Package: trig 1999/03/16 v1.09 sin cos tan (DPC) 837 | ) 838 | (/usr/local/texlive/2014/texmf-dist/tex/latex/latexconfig/graphics.cfg 839 | File: graphics.cfg 2010/04/23 v1.9 graphics configuration of TeX Live 840 | ) 841 | Package graphics Info: Driver file: xetex.def on input line 91. 842 | ) 843 | \Gin@req@height=\dimen177 844 | \Gin@req@width=\dimen178 845 | )) 846 | ................................................. 847 | . LaTeX info: "xparse/define-command" 848 | . 849 | . Defining command \__fontspec_post_arg:w with sig. 'mmO{}' on line 42. 850 | ................................................. 851 | ................................................. 852 | . LaTeX info: "xparse/define-command" 853 | . 854 | . Defining command \fontspec with sig. 'om' on line 44. 855 | ................................................. 856 | ................................................. 857 | . LaTeX info: "xparse/define-command" 858 | . 859 | . Defining command \setmainfont with sig. 'om' on line 54. 860 | ................................................. 861 | ................................................. 862 | . LaTeX info: "xparse/define-command" 863 | . 864 | . Defining command \setsansfont with sig. 'om' on line 64. 865 | ................................................. 866 | ................................................. 867 | . LaTeX info: "xparse/define-command" 868 | . 869 | . Defining command \setmonofont with sig. 'om' on line 74. 870 | ................................................. 871 | ................................................. 872 | . LaTeX info: "xparse/define-command" 873 | . 874 | . Defining command \setmathrm with sig. 'om' on line 88. 875 | ................................................. 876 | ................................................. 877 | . LaTeX info: "xparse/define-command" 878 | . 879 | . Defining command \setboldmathrm with sig. 'om' on line 96. 880 | ................................................. 881 | ................................................. 882 | . LaTeX info: "xparse/define-command" 883 | . 884 | . Defining command \setmathsf with sig. 'om' on line 104. 885 | ................................................. 886 | ................................................. 887 | . LaTeX info: "xparse/define-command" 888 | . 889 | . Defining command \setmathtt with sig. 'om' on line 112. 890 | ................................................. 891 | ................................................. 892 | . LaTeX info: "xparse/define-command" 893 | . 894 | . Defining command \newfontfamily with sig. 'mom' on line 126. 895 | ................................................. 896 | ................................................. 897 | . LaTeX info: "xparse/define-command" 898 | . 899 | . Defining command \newfontface with sig. 'mom' on line 141. 900 | ................................................. 901 | ................................................. 902 | . LaTeX info: "xparse/define-command" 903 | . 904 | . Defining command \defaultfontfeatures with sig. 't+om' on line 155. 905 | ................................................. 906 | ................................................. 907 | . LaTeX info: "xparse/define-command" 908 | . 909 | . Defining command \addfontfeatures with sig. 'm' on line 210. 910 | ................................................. 911 | ................................................. 912 | . LaTeX info: "xparse/define-command" 913 | . 914 | . Defining command \newfontfeature with sig. 'mm' on line 221. 915 | ................................................. 916 | ................................................. 917 | . LaTeX info: "xparse/define-command" 918 | . 919 | . Defining command \newAATfeature with sig. 'mmmm' on line 229. 920 | ................................................. 921 | ................................................. 922 | . LaTeX info: "xparse/define-command" 923 | . 924 | . Defining command \newopentypefeature with sig. 'mmm' on line 237. 925 | ................................................. 926 | ................................................. 927 | . LaTeX info: "xparse/define-command" 928 | . 929 | . Defining command \aliasfontfeature with sig. 'mm' on line 261. 930 | ................................................. 931 | ................................................. 932 | . LaTeX info: "xparse/define-command" 933 | . 934 | . Defining command \aliasfontfeatureoption with sig. 'mmm' on line 270. 935 | ................................................. 936 | ................................................. 937 | . LaTeX info: "xparse/define-command" 938 | . 939 | . Defining command \newfontscript with sig. 'mm' on line 275. 940 | ................................................. 941 | ................................................. 942 | . LaTeX info: "xparse/define-command" 943 | . 944 | . Defining command \newfontlanguage with sig. 'mm' on line 301. 945 | ................................................. 946 | ................................................. 947 | . LaTeX info: "xparse/define-command" 948 | . 949 | . Defining command \DeclareFontsExtensions with sig. 'm' on line 321. 950 | ................................................. 951 | Variant \prop_gput:cnV already defined; not changing it on line 704 952 | Variant \prop_gput:cnx already defined; not changing it on line 705 953 | \l__fontspec_tmp_int=\count161 954 | LaTeX Info: Redefining \itshape on input line 2232. 955 | LaTeX Info: Redefining \slshape on input line 2237. 956 | LaTeX Info: Redefining \scshape on input line 2242. 957 | LaTeX Info: Redefining \upshape on input line 2247. 958 | 959 | (/usr/local/texlive/2014/texmf-dist/tex/latex/fontspec/fontspec.cfg))) 960 | (/usr/local/texlive/2014/texmf-dist/tex/xelatex/xecjk/xunicode-addon.sty 961 | Package: xunicode-addon 2014/12/26 v3.3.0 addon file for xunicode 962 | ................................................. 963 | . LaTeX info: "xparse/redefine-command" 964 | . 965 | . Redefining command \ReloadXunicode with sig. 'm' on line 89. 966 | ................................................. 967 | ................................................. 968 | . LaTeX info: "xparse/redefine-command" 969 | . 970 | . Redefining command \DeclareUTFmathsymbols with sig. 'm' on line 124. 971 | ................................................. 972 | ................................................. 973 | . LaTeX info: "xparse/redefine-command" 974 | . 975 | . Redefining command \UseMathAsText with sig. '' on line 133. 976 | ................................................. 977 | ................................................. 978 | . LaTeX info: "xparse/redefine-command" 979 | . 980 | . Redefining command \UndeclareUTFcharacter with sig. 'O{\UTFencname }mm' on 981 | . line 168. 982 | ................................................. 983 | ................................................. 984 | . LaTeX info: "xparse/redefine-command" 985 | . 986 | . Redefining command \UndeclareUTFcomposite with sig. 'O{\UTFencname }mmm' on 987 | . line 175. 988 | ................................................. 989 | ................................................. 990 | . LaTeX info: "xparse/redefine-command" 991 | . 992 | . Redefining command \DeclareUTFcharacter with sig. 'O{\UTFencname }mm' on 993 | . line 202. 994 | ................................................. 995 | ................................................. 996 | . LaTeX info: "xparse/define-command" 997 | . 998 | . Defining command \DeclareUTFSymbol with sig. 'mO{\UTFencname }m' on line 999 | . 228. 1000 | ................................................. 1001 | ................................................. 1002 | . LaTeX info: "xparse/define-command" 1003 | . 1004 | . Defining command \DeclareUTFCommand with sig. 'mO{\UTFencname }m' on line 1005 | . 230. 1006 | ................................................. 1007 | ................................................. 1008 | . LaTeX info: "xparse/redefine-command" 1009 | . 1010 | . Redefining command \DeclareUTFcomposite with sig. 'O{\UTFencname }mmm' on 1011 | . line 273. 1012 | ................................................. 1013 | ................................................. 1014 | . LaTeX info: "xparse/define-command" 1015 | . 1016 | . Defining command \DeclareUTFCompositeCommand with sig. 'mO{\UTFencname }mm' 1017 | . on line 286. 1018 | ................................................. 1019 | ................................................. 1020 | . LaTeX info: "xparse/define-command" 1021 | . 1022 | . Defining command \DeclareUTFCompositeSymbol with sig. 'mO{\UTFencname }mm' 1023 | . on line 291. 1024 | ................................................. 1025 | ................................................. 1026 | . LaTeX info: "xparse/define-command" 1027 | . 1028 | . Defining command \DeclareUTFComposite with sig. 'mO{\UTFencname }' on line 1029 | . 293. 1030 | ................................................. 1031 | ................................................. 1032 | . LaTeX info: "xparse/define-command" 1033 | . 1034 | . Defining command \DeclareUTFEncodedAccent with sig. 'mO{\UTFencname }mm' on 1035 | . line 295. 1036 | ................................................. 1037 | ................................................. 1038 | . LaTeX info: "xparse/define-command" 1039 | . 1040 | . Defining command \DeclareUTFEncodedAccents with sig. 'mO{\UTFencname }mm' on 1041 | . line 297. 1042 | ................................................. 1043 | ................................................. 1044 | . LaTeX info: "xparse/define-command" 1045 | . 1046 | . Defining command \DeclareUTFEncodedSymbol with sig. 'mO{\UTFencname }mm' on 1047 | . line 299. 1048 | ................................................. 1049 | ................................................. 1050 | . LaTeX info: "xparse/define-command" 1051 | . 1052 | . Defining command \DeclareUTFEncodedCircle with sig. 'mO{\UTFencname }mm' on 1053 | . line 301. 1054 | ................................................. 1055 | ................................................. 1056 | . LaTeX info: "xparse/redefine-command" 1057 | . 1058 | . Redefining command \DeclareEncodedCompositeCharacter with sig. 'mmmm' on 1059 | . line 303. 1060 | ................................................. 1061 | ................................................. 1062 | . LaTeX info: "xparse/redefine-command" 1063 | . 1064 | . Redefining command \DeclareEncodedCompositeAccents with sig. 'mmmm' on line 1065 | . 305. 1066 | ................................................. 1067 | ................................................. 1068 | . LaTeX info: "xparse/define-command" 1069 | . 1070 | . Defining command \DeclareUTFDoubleEncodedAccent with sig. 'mO{\UTFencname 1071 | . }mm' on line 307. 1072 | ................................................. 1073 | ................................................. 1074 | . LaTeX info: "xparse/define-command" 1075 | . 1076 | . Defining command \DeclareUTFDoubleEncodedSymbol with sig. 'mO{\UTFencname 1077 | . }mm' on line 309. 1078 | ................................................. 1079 | \l__xunadd_tmp_coffin=\box50 1080 | \l__xunadd_circle_coffin=\box51 1081 | ................................................. 1082 | . LaTeX info: "xparse/define-command" 1083 | . 1084 | . Defining command \settextcircledratio with sig. 'm' on line 460. 1085 | ................................................. 1086 | ................................................. 1087 | . LaTeX info: "xparse/define-command" 1088 | . 1089 | . Defining command \AtBeginUTFCommand with sig. 'sO{}+m' on line 529. 1090 | ................................................. 1091 | ................................................. 1092 | . LaTeX info: "xparse/define-command" 1093 | . 1094 | . Defining command \AtEndUTFCommand with sig. 'sO{}+m' on line 539. 1095 | ................................................. 1096 | ................................................. 1097 | . LaTeX info: "xparse/define-command" 1098 | . 1099 | . Defining command \DeclareUTFTIPACommand with sig. 'O{\UTFencname }m' on line 1100 | . 571. 1101 | ................................................. 1102 | ) 1103 | \g__file_internal_ior=\read1 1104 | 1105 | (/usr/local/texlive/2014/texmf-dist/tex/xelatex/xunicode/xunicode.sty 1106 | File: xunicode.sty 2011/09/09 v0.981 provides access to latin accents and many 1107 | other characters in Unicode lower plane 1108 | 1109 | *** Reloading Xunicode for encoding 'EU1' *** 1110 | ) (/usr/local/texlive/2014/texmf-dist/tex/xelatex/xecjk/xunicode-extra.def 1111 | File: xunicode-extra.def 2014/12/26 v3.3.0 extra definition for xunicode 1112 | ) 1113 | ................................................. 1114 | . LaTeX info: "xparse/define-command" 1115 | . 1116 | . Defining command \xeCJKsetup with sig. '+m' on line 3545. 1117 | ................................................. 1118 | ................................................. 1119 | . LaTeX info: "xparse/define-command" 1120 | . 1121 | . Defining command \xeCJKsetemboldenfactor with sig. 'm' on line 3547. 1122 | ................................................. 1123 | ................................................. 1124 | . LaTeX info: "xparse/define-command" 1125 | . 1126 | . Defining command \xeCJKsetslantfactor with sig. 'm' on line 3549. 1127 | ................................................. 1128 | ................................................. 1129 | . LaTeX info: "xparse/define-command" 1130 | . 1131 | . Defining command \punctstyle with sig. 'm' on line 3550. 1132 | ................................................. 1133 | ................................................. 1134 | . LaTeX info: "xparse/define-command" 1135 | . 1136 | . Defining command \xeCJKplainchr with sig. '' on line 3551. 1137 | ................................................. 1138 | ................................................. 1139 | . LaTeX info: "xparse/define-command" 1140 | . 1141 | . Defining command \CJKsetecglue with sig. 'm' on line 3552. 1142 | ................................................. 1143 | ................................................. 1144 | . LaTeX info: "xparse/define-command" 1145 | . 1146 | . Defining command \CJKspace with sig. '' on line 3554. 1147 | ................................................. 1148 | ................................................. 1149 | . LaTeX info: "xparse/define-command" 1150 | . 1151 | . Defining command \CJKnospace with sig. '' on line 3555. 1152 | ................................................. 1153 | ................................................. 1154 | . LaTeX info: "xparse/define-command" 1155 | . 1156 | . Defining command \xeCJKallowbreakbetweenpuncts with sig. '' on line 3557. 1157 | ................................................. 1158 | ................................................. 1159 | . LaTeX info: "xparse/define-command" 1160 | . 1161 | . Defining command \xeCJKnobreakbetweenpuncts with sig. '' on line 3559. 1162 | ................................................. 1163 | ................................................. 1164 | . LaTeX info: "xparse/define-command" 1165 | . 1166 | . Defining command \xeCJKenablefallback with sig. '' on line 3561. 1167 | ................................................. 1168 | ................................................. 1169 | . LaTeX info: "xparse/define-command" 1170 | . 1171 | . Defining command \xeCJKdisablefallback with sig. '' on line 3563. 1172 | ................................................. 1173 | ................................................. 1174 | . LaTeX info: "xparse/define-command" 1175 | . 1176 | . Defining command \xeCJKsetcharclass with sig. 'mmm' on line 3568. 1177 | ................................................. 1178 | ................................................. 1179 | . LaTeX info: "xparse/redefine-command" 1180 | . 1181 | . Redefining command \nobreakspace with sig. '' on line 3682. 1182 | ................................................. 1183 | ................................................. 1184 | . LaTeX info: "xparse/redefine-command" 1185 | . 1186 | . Redefining command \fontfamily with sig. 'm' on line 3728. 1187 | ................................................. 1188 | 1189 | (/usr/local/texlive/2014/texmf-dist/tex/xelatex/xecjk/config/xeCJK.cfg 1190 | File: xeCJK.cfg 2014/12/26 v3.3.0 Configuration file for xeCJK package 1191 | )) 1192 | ************************************************* 1193 | * fontspec warning: "script-not-exist" 1194 | * 1195 | * Font 'STHeitiSC-Light' does not contain script 'CJK'. 1196 | ************************************************* 1197 | \g__fontspec_family_STHeitiSC-Light_int=\count162 1198 | ................................................. 1199 | . fontspec info: "no-font-shape" 1200 | . 1201 | . Could not resolve font STHeitiSC-Light/I (it probably doesn't exist). 1202 | ................................................. 1203 | ................................................. 1204 | . fontspec info: "defining-font" 1205 | . 1206 | . Font family 'STHeitiSC-Light(0)' created for font 'STHeitiSC-Light' with 1207 | . options [Script={CJK}]. 1208 | . 1209 | . This font family consists of the following shapes: 1210 | . 1211 | . * 'normal' with NFSS spec.: 1212 | . <->"STHeitiSC-Light/OT:" 1213 | . 1214 | . * 'small caps' with NFSS spec.: 1215 | . 1216 | . and font adjustment code: 1217 | . 1218 | . 1219 | . * 'bold' with NFSS spec.: 1220 | . <->"STHeitiSC-Light/B/OT:" 1221 | . 1222 | . * 'bold small caps' with NFSS spec.: 1223 | . 1224 | . and font adjustment code: 1225 | . 1226 | . 1227 | . * 'bold italic' with NFSS spec.: 1228 | . <->"STHeitiSC-Light/BI/OT:" 1229 | . 1230 | . * 'bold small caps' with NFSS spec.: 1231 | . 1232 | . and font adjustment code: 1233 | . 1234 | ................................................. 1235 | ................................................. 1236 | . fontspec info: "no-scripts" 1237 | . 1238 | . Font Times-Roman does not contain any OpenType `Script' information. 1239 | ................................................. 1240 | \g__fontspec_family_Times-Roman_int=\count163 1241 | ................................................. 1242 | . fontspec info: "defining-font" 1243 | . 1244 | . Font family 'Times-Roman(0)' created for font 'Times-Roman' with options []. 1245 | . 1246 | . This font family consists of the following shapes: 1247 | . 1248 | . * 'normal' with NFSS spec.: 1249 | . <->"Times-Roman/AAT:" 1250 | . 1251 | . * 'small caps' with NFSS spec.: 1252 | . 1253 | . and font adjustment code: 1254 | . 1255 | . 1256 | . * 'bold' with NFSS spec.: 1257 | . <->"Times-Roman/B/AAT:" 1258 | . 1259 | . * 'bold small caps' with NFSS spec.: 1260 | . 1261 | . and font adjustment code: 1262 | . 1263 | . 1264 | . * 'italic' with NFSS spec.: 1265 | . <->"Times-Roman/I/AAT:" 1266 | . 1267 | . * 'small caps' with NFSS spec.: 1268 | . 1269 | . and font adjustment code: 1270 | . 1271 | . 1272 | . * 'bold italic' with NFSS spec.: 1273 | . <->"Times-Roman/BI/AAT:" 1274 | . 1275 | . * 'bold small caps' with NFSS spec.: 1276 | . 1277 | . and font adjustment code: 1278 | . 1279 | ................................................. 1280 | \g__fontspec_family_PTMono-Regular_int=\count164 1281 | ................................................. 1282 | . fontspec info: "no-font-shape" 1283 | . 1284 | . Could not resolve font PTMono-Regular/I (it probably doesn't exist). 1285 | ................................................. 1286 | ................................................. 1287 | . fontspec info: "defining-font" 1288 | . 1289 | . Font family 'PTMono-Regular(0)' created for font 'PTMono-Regular' with 1290 | . options []. 1291 | . 1292 | . This font family consists of the following shapes: 1293 | . 1294 | . * 'normal' with NFSS spec.: 1295 | . <->"PTMono-Regular/OT:script=latn;language=DFLT;" 1296 | . 1297 | . * 'small caps' with NFSS spec.: 1298 | . 1299 | . and font adjustment code: 1300 | . 1301 | . 1302 | . * 'bold' with NFSS spec.: 1303 | . <->"PTMono-Regular/B/OT:script=latn;language=DFLT;" 1304 | . 1305 | . * 'bold small caps' with NFSS spec.: 1306 | . 1307 | . and font adjustment code: 1308 | . 1309 | . 1310 | . * 'bold italic' with NFSS spec.: 1311 | . <->"PTMono-Regular/BI/OT:script=latn;language=DFLT;" 1312 | . 1313 | . * 'bold small caps' with NFSS spec.: 1314 | . 1315 | . and font adjustment code: 1316 | . 1317 | ................................................. 1318 | LaTeX Info: Redefining \M on input line 37. 1319 | (/usr/local/texlive/2014/texmf-dist/tex/xelatex/xecjk/xeCJK-listings.sty 1320 | Package: xeCJK-listings 2014/12/26 v3.3.0 xeCJK patch file for listings 1321 | \l__xeCJK_listings_flag_int=\count165 1322 | ) 1323 | 1324 | LaTeX Warning: Unused global option(s): 1325 | [8pt]. 1326 | 1327 | (./EffectiveModernCppCN.aux) 1328 | \openout1 = `EffectiveModernCppCN.aux'. 1329 | 1330 | LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 39. 1331 | LaTeX Font Info: ... okay on input line 39. 1332 | LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 39. 1333 | LaTeX Font Info: ... okay on input line 39. 1334 | LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 39. 1335 | LaTeX Font Info: ... okay on input line 39. 1336 | LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 39. 1337 | LaTeX Font Info: ... okay on input line 39. 1338 | LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 39. 1339 | LaTeX Font Info: ... okay on input line 39. 1340 | LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 39. 1341 | LaTeX Font Info: ... okay on input line 39. 1342 | LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 39. 1343 | LaTeX Font Info: ... okay on input line 39. 1344 | LaTeX Font Info: Checking defaults for PU/pdf/m/n on input line 39. 1345 | LaTeX Font Info: ... okay on input line 39. 1346 | LaTeX Font Info: Checking defaults for EU1/lmr/m/n on input line 39. 1347 | LaTeX Font Info: ... okay on input line 39. 1348 | LaTeX Font Info: Checking defaults for T3/cmr/m/n on input line 39. 1349 | LaTeX Font Info: Try loading font information for T3+cmr on input line 39. 1350 | 1351 | (/usr/local/texlive/2014/texmf-dist/tex/latex/tipa/t3cmr.fd 1352 | File: t3cmr.fd 2001/12/31 TIPA font definitions 1353 | ) 1354 | LaTeX Font Info: ... okay on input line 39. 1355 | 1356 | *geometry* driver: auto-detecting 1357 | *geometry* detected driver: xetex 1358 | *geometry* verbose mode - [ preamble ] result: 1359 | * driver: xetex 1360 | * paper: a4paper 1361 | * layout: 1362 | * layoutoffset:(h,v)=(0.0pt,0.0pt) 1363 | * modes: twoside 1364 | * h-part:(L,W,R)=(90.3375pt, 416.83289pt, 90.3375pt) 1365 | * v-part:(T,H,B)=(72.26999pt, 700.50687pt, 72.26999pt) 1366 | * \paperwidth=597.50787pt 1367 | * \paperheight=845.04684pt 1368 | * \textwidth=416.83289pt 1369 | * \textheight=700.50687pt 1370 | * \oddsidemargin=18.0675pt 1371 | * \evensidemargin=18.0675pt 1372 | * \topmargin=-30.06749pt 1373 | * \headheight=12.0pt 1374 | * \headsep=18.06749pt 1375 | * \topskip=10.0pt 1376 | * \footskip=25.29494pt 1377 | * \marginparwidth=115.0pt 1378 | * \marginparsep=7.0pt 1379 | * \columnsep=10.0pt 1380 | * \skip\footins=9.0pt plus 4.0pt minus 2.0pt 1381 | * \hoffset=0.0pt 1382 | * \voffset=0.0pt 1383 | * \mag=1000 1384 | * \@twocolumnfalse 1385 | * \@twosidetrue 1386 | * \@mparswitchtrue 1387 | * \@reversemarginfalse 1388 | * (1in=72.27pt=25.4mm, 1cm=28.453pt) 1389 | 1390 | \AtBeginShipoutBox=\box52 1391 | Package hyperref Info: Link coloring ON on input line 39. 1392 | (/usr/local/texlive/2014/texmf-dist/tex/latex/hyperref/nameref.sty 1393 | Package: nameref 2012/10/27 v2.43 Cross-referencing by name of section 1394 | 1395 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/gettitlestring.sty 1396 | Package: gettitlestring 2010/12/03 v1.4 Cleanup title references (HO) 1397 | ) 1398 | \c@section@level=\count166 1399 | ) 1400 | LaTeX Info: Redefining \ref on input line 39. 1401 | LaTeX Info: Redefining \pageref on input line 39. 1402 | LaTeX Info: Redefining \nameref on input line 39. 1403 | 1404 | (./EffectiveModernCppCN.out) (./EffectiveModernCppCN.out) 1405 | \@outlinefile=\write3 1406 | \openout3 = `EffectiveModernCppCN.out'. 1407 | 1408 | \c@lstlisting=\count167 1409 | LaTeX Font Info: Try loading font information for OT1+lmr on input line 45. 1410 | 1411 | (/usr/local/texlive/2014/texmf-dist/tex/latex/lm/ot1lmr.fd 1412 | File: ot1lmr.fd 2009/10/30 v1.6 Font defs for Latin Modern 1413 | ) 1414 | LaTeX Font Info: Try loading font information for OML+lmm on input line 45. 1415 | 1416 | (/usr/local/texlive/2014/texmf-dist/tex/latex/lm/omllmm.fd 1417 | File: omllmm.fd 2009/10/30 v1.6 Font defs for Latin Modern 1418 | ) 1419 | LaTeX Font Info: Try loading font information for OMS+lmsy on input line 45. 1420 | 1421 | 1422 | (/usr/local/texlive/2014/texmf-dist/tex/latex/lm/omslmsy.fd 1423 | File: omslmsy.fd 2009/10/30 v1.6 Font defs for Latin Modern 1424 | ) 1425 | LaTeX Font Info: Try loading font information for OMX+lmex on input line 45. 1426 | 1427 | 1428 | (/usr/local/texlive/2014/texmf-dist/tex/latex/lm/omxlmex.fd 1429 | File: omxlmex.fd 2009/10/30 v1.6 Font defs for Latin Modern 1430 | ) 1431 | LaTeX Font Info: External font `lmex10' loaded for size 1432 | (Font) <12> on input line 45. 1433 | LaTeX Font Info: External font `lmex10' loaded for size 1434 | (Font) <8> on input line 45. 1435 | LaTeX Font Info: External font `lmex10' loaded for size 1436 | (Font) <6> on input line 45. 1437 | 1438 | (/usr/local/texlive/2014/texmf-dist/tex/generic/oberdiek/se-ascii-print.def 1439 | File: se-ascii-print.def 2011/12/02 v1.10 stringenc: Printable ASCII characters 1440 | 1441 | ) 1442 | [1 1443 | 1444 | 1445 | ] [2 1446 | 1447 | ] (./EffectiveModernCppCN.toc 1448 | LaTeX Font Info: External font `lmex10' loaded for size 1449 | (Font) <10> on input line 2. 1450 | LaTeX Font Info: External font `lmex10' loaded for size 1451 | (Font) <7> on input line 2. 1452 | LaTeX Font Info: External font `lmex10' loaded for size 1453 | (Font) <5> on input line 2. 1454 | ) 1455 | \tf@toc=\write4 1456 | \openout4 = `EffectiveModernCppCN.toc'. 1457 | 1458 | (./Chapter1/chapter1.tex [3] [4 1459 | 1460 | ] 1461 | Chapter 1. 1462 | (./Chapter1/item1.tex [5] 1463 | 1464 | LaTeX Font Warning: Font shape `EU1/STHeitiSC-Light(0)/m/sl' undefined 1465 | (Font) using `EU1/STHeitiSC-Light(0)/m/n' instead on input line 88 1466 | . 1467 | 1468 | [6] [7] [8] [9] 1469 | Package mdframed Info: mdframed works in twoside mode on input line 286. 1470 | ) (./Chapter1/item2.tex [10] [11] [12] [13] 1471 | Package mdframed Info: mdframed works in twoside mode on input line 195. 1472 | ) 1473 | (./Chapter1/item3.tex [14] [15] [16] 1474 | Package mdframed Info: mdframed works in twoside mode on input line 198. 1475 | [17] 1476 | Package mdframed Info: Not enough space on this page on input line 204. 1477 | ) (./Chapter1/item4.tex [18] [19] 1478 | Overfull \hbox (51.53711pt too wide) in paragraph at lines 157--158 1479 | \EU1/lmr/m/n/10 volatile \EU1/STHeitiSC-Light(0)/m/n/10 或 者 引 用 修 饰 符 \EU1/lmr/ 1480 | m/n/10 (\EU1/STHeitiSC-Light(0)/m/n/10 所 以 函 数 名 带 有 一 个 |“\EU1/lmr/m/n/10 wit 1481 | h_cvr\EU1/STHeitiSC-Light(0)/m/n/10 ”| \EU1/lmr/m/n/10 )\EU1/STHeitiSC-Light(0) 1482 | /m/n/10 。| 其 返 回 结 果 是 一 个 \EU1/lmr/m/n/10 boost::typeindex::type_index 1483 | [] 1484 | 1485 | [20] 1486 | Overfull \hbox (12.92491pt too wide) in paragraph at lines 186--187 1487 | []\EU1/STHeitiSC-Light(0)/m/n/10 这 种 近 乎 一 致 的 表 示 是 很 好 的,| 但 是 也 要 记 住 \EU1/ 1488 | lmr/m/n/10 IDE \EU1/STHeitiSC-Light(0)/m/n/10 编 辑 器,| 编 译 错 误 信 息 或 者 类 似 \EU1 1489 | /lmr/m/n/10 Boost.TypeIndex 1490 | [] 1491 | 1492 | Package mdframed Info: mdframed works in twoside mode on input line 189. 1493 | )) (./Chapter2/chapter2.tex [21] [22 1494 | 1495 | ] 1496 | Chapter 2. 1497 | (./Chapter2/item6.tex [23] [24] 1498 | Overfull \hbox (3.69711pt too wide) in paragraph at lines 89--90 1499 | \EU1/STHeitiSC-Light(0)/m/n/10 函 数 调 用 的 返 回 值 上,| 所 以 函 数 签 名 通 常 能 够 反 映 它 们 1500 | 的 存 在。| 这 是 \EU1/lmr/m/n/10 std::vector::operator[] 1501 | [] 1502 | 1503 | 1504 | Overfull \hbox (50.1071pt too wide) in paragraph at lines 114--115 1505 | \EU1/STHeitiSC-Light(0)/m/n/10 型 成 了 \EU1/lmr/m/n/10 bool\EU1/STHeitiSC-Light(0 1506 | )/m/n/10 ,| 因 此 \EU1/lmr/m/n/10 auto \EU1/STHeitiSC-Light(0)/m/n/10 能 够 将 \EU1 1507 | /lmr/m/n/10 highPriority \EU1/STHeitiSC-Light(0)/m/n/10 的 类 型 推 导 成 \EU1/lmr/m/ 1508 | n/10 bool\EU1/STHeitiSC-Light(0)/m/n/10 。| 在 运 行 过 程 中,| \EU1/lmr/m/n/10 std:: 1509 | vector::operator[] 1510 | [] 1511 | 1512 | [25] 1513 | Package mdframed Info: mdframed works in twoside mode on input line 153. 1514 | 1515 | 1516 | LaTeX Warning: Reference `mdf@pagelabel-5' on page 26 undefined on input line 1 1517 | 58. 1518 | 1519 | )) 1520 | Package atveryend Info: Empty hook `BeforeClearDocument' on input line 51. 1521 | [26] 1522 | Package atveryend Info: Empty hook `AfterLastShipout' on input line 51. 1523 | (./EffectiveModernCppCN.aux) 1524 | Package atveryend Info: Empty hook `AtVeryEndDocument' on input line 51. 1525 | Package atveryend Info: Empty hook `AtEndAfterFileList' on input line 51. 1526 | 1527 | 1528 | LaTeX Font Warning: Some font shapes were not available, defaults substituted. 1529 | 1530 | 1531 | LaTeX Warning: There were undefined references. 1532 | 1533 | 1534 | LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. 1535 | 1536 | ) 1537 | Here is how much of TeX's memory you used: 1538 | 26874 strings out of 493724 1539 | 517389 string characters out of 6145899 1540 | 793022 words of memory out of 5000000 1541 | 29915 multiletter control sequences out of 15000+600000 1542 | 26059 words of font info for 65 fonts, out of 8000000 for 9000 1543 | 1328 hyphenation exceptions out of 8191 1544 | 52i,6n,69p,10428b,1045s stack positions out of 5000i,500n,10000p,200000b,80000s 1545 | 1546 | Output written on EffectiveModernCppCN.pdf (26 pages). 1547 | --------------------------------------------------------------------------------