下午好,亲爱的读者!
本文是我阅读Scott Meyers畅销书《 Effective and Modern c ++》时所写的一系列抽象文章中的第二篇。 在github.com上专门建立的项目中,每一篇文章都将有一个单独的目录, 其中包含使用我们今天所读内容的实时示例。
本文对上一篇文章的类型推断规则进行了补充,并讨论了作为数组和函数的参数的模板类型推断的某些方面。
数组的模式类型推断
c ++编译器具有这样的属性:当将声明的数组始终传递给带有未声明为链接的参数的模板函数时,始终会转换为指向存储类型的指针,反之亦然,如果将参数声明为链接,则不会执行这种转换。
模板功能:
首先,我将提供模板函数的代码,这些代码推导出令人垂涎的类型,然后推导过程本身:
template<typename T> void paramDeductInfo(T param, const char *initType) { std::cout << initType << " -> (T param) -> " << type_id_with_cvr<T>().pretty_name() << std::endl; }; template<typename T> void refParamDeductInfo(T ¶m, const char *initType) { std::cout << initType << " -> (T ¶m) -> " << type_id_with_cvr<T>().pretty_name() << std::endl; };
类型推断:
cli::printCaption("TYPE DEDUCTION FOR ARRAY OF CHAR"); char charSeq[] = "Hi everyone!"; paramDeductInfo(charSeq, "char []"); refParamDeductInfo(charSeq, "char []"); cli::printCaption("TYPE DEDUCTION FOR ARRAY OF INT"); int intSeq[] = {1, 2, 3}; paramDeductInfo(intSeq, "int []"); refParamDeductInfo(intSeq, "int []"); cli::printCaption("TYPE DEDUCTION FOR ARRAY OF CLASS A"); class A { } const classASeq[] = {A(), A(), A()}; paramDeductInfo(classASeq, "class A[]"); refParamDeductInfo(classASeq, "class A[]");
以下伪代码将这些指令的输出反映到控制台:
************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CHAR ************************************************************************************************************************ char [] -> (T param) -> char* char [] -> (T ¶m) -> char [13] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF INT ************************************************************************************************************************ int [] -> (T param) -> int* int [] -> (T ¶m) -> int [3] ************************************************************************************************************************ TYPE DEDUCTION FOR ARRAY OF CLASS A ************************************************************************************************************************ class A[] -> (T param) -> main::A const* class A[] -> (T ¶m) -> main::A const [3]
示例1-分析编译时数组的长度
此外,数组的输出类型存储有关其大小的信息,可在模板函数中使用该信息来在编译过程中操纵数组的大小或生成更有效的代码。
我在printCaption函数中使用了此功能,以限制编译时在命令行上显示的标头长度。 有点琐事,但很好。
namespace cli { template<typename T, std::size_t N> constexpr void printCaption(T (&capValue)[N]) { static_assert(N <= 121, "caption length should be less than 120"); std::cout << std::endl << "*******************************************************************************" << std::endl << capValue << std::endl << "*******************************************************************************" << std::endl << std::endl; }; }
如果引入明显不合适的标头,让我们检查是否会出现错误。
cli::printCaption("123456789 123456789 123456789 123456789 123456789 123456789 123456789" "123456789 123456789 123456789 123456789 123456789 !");
您在这里,好吧,这不是很好吗?
/...sources/cli.h:12:3: error: static assertion failed: caption length should be less than 120 static_assert(N <= 121, "caption length should be less than 120"); ^~~~~~~~~~~~~
示例2-内存中数组上的foreach
我认为这是另一种这样的方法,如果我们在编译时具有数组大小,这似乎有用,为什么不使用它来组织此类数组上的循环?
template<typename T, size_t N, typename F> void forEachOnAnArray(T (&inmemArray)[N], F &callback) { for (int i = 0; i < N; ++i) callback(inmemArray[i]); };
使用此功能的方法如下:
auto printInt = [](int value) { std::cout << " " << value; }; forEachOnAnArray(intSeq, printInt);
通常,使用此功能绝不限于拉出阵列的大小。
函数的类型推断
说到Meyers函数的类型推断很简洁。 他确切地提到将它们简化为与数组相同的指针,除非未将要显示我们的函数类型的模板函数的参数声明为链接。
他可能应该讨论某种函数的模板包装器,但是我想这不仅仅涉及高效和现代的c ++问题。
亲爱的读者,我们一定会回到这个问题!
谢谢,祝你有美好的一天!