template <class T, class U> decltype(*(T*)(0) * *(U*)(0)) mul(T x, U y) {
return x * y;
}
Run Code Online (Sandbox Code Playgroud)
这段代码取自Stroustrup的C++ 11 FAQ.我理解它的作用,它是两个不同类型的对象相乘.令我困惑的是模板参数和函数定义之间的语法.里面发生了什么decltype?我认为它取消引用一个T初始化为0的未命名U指针,并将它与一个未命名的指针相乘,并以相同的方式进行解引用和初始化.我对吗?
好吧,如果这是正在发生的事情,那么指针,解引用和额外括号的使用是不是多余的?我不能在保持预期效果的同时初始化这样的类型吗?:
template <class T, class U> decltype(T(0) * U(0)) mul(T x, U y) {
return x * y;
}
Run Code Online (Sandbox Code Playgroud)
这对我来说看起来更干净,并且当像第一个那样乘以两个数字时它确实具有相同的效果......
mul(4, 3); // 12
Run Code Online (Sandbox Code Playgroud)
那么为什么Stroustrup坚持使用复杂的指针,解引用和初始化语法?当然,这是在他介绍新auto语法之前.但无论如何,我的问题是:上述两种形式的初始化之间有什么区别吗?他在哪里使用指针并立即取消引用它们而不是简单地做我所做的,这是用没有指针或解除引用来初始化类型?任何回应表示赞赏.
您的版本不相同.
T并U可以从构建0.从矩阵中预期这一点显然是错误的,但它们可以成倍增加.T(0)产生临时(可能绑定T&&),同时*(T*(0))产生对现有对象的引用(即,T&),因此可能选择不同的运算符.但是,Stroustrup的版本和你的版本最终都没有在实践中使用.在相同级别的编译器实现中,可以使用:
template <typename T, typename U>
decltype(std::declval<T>() * std::declval<U>()) mul(T x, U y);
Run Code Online (Sandbox Code Playgroud)
但是它没有利用Late Return Type规范,它被允许在函数的参数声明之后推迟返回类型的声明:auto f(int, int) -> int.一旦声明了参数,就可以使用它们,这非常有用decltype!
template <typename T, typename U>
auto mul(T x, U y) -> decltype(x * y);
Run Code Online (Sandbox Code Playgroud)
保证后一种形式选择与功能体相同的操作员过载,代价是重复(不幸的是).
您的代码版本假设T和U具有默认构造函数.Stroustrup版本没有,它通过取消引用空指针来创建一个虚拟对象.当然,这并不重要,因为该代码并不意味着要执行,它只是要解析才能知道结果类型.
| 归档时间: |
|
| 查看次数: |
195 次 |
| 最近记录: |