问题的要点是,在调用我的(模板)函数时,我已经定义了默认值的参数将其值加扰.只有当我使用默认值调用该函数时才会发生.
我的模板函数是这样声明的:
template <typename T> vector2<T> transform(vector2<T> const &vec,matrix4<T> const &m,T z = T(0),T w = T(1));
后来,在同一个标题中,定义如下:
template <typename T> inline vector2<T> transform(vector2<T> const &vec,T z,T w) { vector4<T> res = m * vector4<T>(vec.x,vec.y,z,w); return vector2<T>(res.x,res.y); }
现在当我使用默认值(transform(vector2< double>(0,1),view_transform))调用它时))我没有得到我期望的值.使用VC调试器进行转换,我看到z和w具有“有趣”值(根据我的经验意味着某些东西没有被正确初始化).
示例有趣的值将是:0.0078125000000000000和2.104431116947e-317#DEN
现在我已经尝试找到C FAQ Lite的答案,搜索它;甚至试图用舒伯特冷静自己,但我不能为我的生活弄清楚.我猜这很简单,我怀疑它是在工作中的某种模板tomfoolery.
有没有办法获得我期望和想要的默认值,为什么要这样做呢?
编辑1:
如果我改变调用,那么它使用浮点代码(transform(vector2< float>(0,view_transform)),问题消失了.看来这只有在T =双倍时才会发生.
编辑2:
只有当我有两个专业的double和float时才会发生.如果我在一个地方使用浮动专业化,那么双重专业化将会产生奇怪的默认值.如果我更改所有的函数调用的地方,所以它使用了两倍的问题“消失”.我仍然不明白为什么,它就像使用错误的偏移或设置z和w时的东西.
编辑3:
来自C Crypt的故事:
#include <sgt/matrix4.hpp> int main(int argc,char *argv[]) { sgt::matrix4<double> m0( 2,1,2,1); m0 *= m0; sgt::vector2<double> blah0 = sgt::transform(sgt::vector2<double>(1,0),m0); sgt::matrix4<float> m1( 2,1); m1 *= m1; sgt::vector2<float> blah1 = sgt::transform(sgt::vector2<float>(1,m1); printf("%f",blah0.x); printf("%f",blah1.x); }
在matrix4.hpp中
// ... template <typename T> vector2<T> transform(vector2<T> const &vec,T w = T(1)); template <typename T> inline vector2<T> transform(vector2<T> const &vec,T w) { vector4<T> res = m * vector4<T>(vec.x,w); return vector2<T>(res.x,res.y); } // ...
如果我运行它,双精度的默认参数是正确的,但是float版本的默认参数为零(0.000000),尽管如此,它仍然不是z = 0和w = 1.
编辑4:
解决方法
#include "stdafx.h" #include <vector> #include <iostream> template <typename T> std::vector<std::vector<T> > transform(std::vector<std::vector<T> > const &vec,std::vector<std::vector<std::vector<std::vector<T> > > > const &m,T w = T(1)); template <typename T> std::vector<std::vector<T> > transform(std::vector<std::vector<T> > const &vec,T w) { std::cout << "Z" << z << "\n"; std::cout << "W" << w << "\n"; return vec; } int _tmain(int argc,_TCHAR* argv[]) { std::vector<std::vector<int> > xi; std::vector<std::vector<std::vector<std::vector<int> > > > mi; transform(xi,mi); std::vector<std::vector<float> > xf; std::vector<std::vector<std::vector<std::vector<float> > > > mf; transform(xf,mf); std::vector<std::vector<double> > xd; std::vector<std::vector<std::vector<std::vector<double> > > > md; transform(xd,md); }
输出:
Z0 W1 Z0 W1.4013e-045 Z2.122e-314 W3.60689e-305
所以我想它不能像预期的那样工作!
如果删除预声明并将默认参数放在模板函数中,则它将按预期工作.
#include "stdafx.h" #include <vector> #include <iostream> template <typename T> std::vector<std::vector<T> > transform(std::vector<std::vector<T> > const &vec,std::vector<std::vector<std::vector<std::vector<T> > > > const &m T z = T(0),T w = T(1)) { std::cout << "Z" << z << "\n"; std::cout << "W" << w << "\n"; return vec; } int _tmain(int argc,md); }
这样可以预期.
这与模板预声明无关,实际上并不是一个函数预声明,因此它实际上没有默认参数,因此您将在参数列表中获取随机值.
好.不是从我阅读的标准,这应该按预期工作:
使用n2521
第14.7.1节隐式实例化
第9段
An implementation shall not implicitly instantiate a function template,a member template,a non-virtual member func- tion,a member class or a static data member of a class template that does not require instantiation. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated. The use of a template specialization in a default argument shall not cause the template to be implicitly instantiated except that a class template may be instantiated where its complete type is needed to determine the correctness of the default argument. The use of a default argument in a function call causes specializations in the default argument to be implicitly instantiated.
段落的粗体部分似乎(对我来说),表示由于默认参数创建的每个专业化将被使用时隐式地实例化到翻译单元中.
第11段:
If a function template f is called in a way that requires a default argument expression to be used,the dependent names are looked up,the semantics constraints are checked,and the instantiation of any template used in the default argument expression is done as if the default argument expression had been an expression used in a function template specialization with the same scope,the same template parameters and the same access as that of the function template f used at that point. This analysis is called default argument instantiation. The instantiated default argument is then used as the argument of f.
表示即使默认参数是模板参数,它们也将被正确实例化.
我希望我能正确地解释.