还是模板缺省参数问题?

OOPhaisky 2006-06-25 02:17:11
C++ primer中:
“类模板的后续声明可以为模板参数提供附加的缺省实参。正如函数参数的缺省实参的情形一样。在向左边的参数提供缺省实参之前,必须首先给最右边未初始化的参数提供缺省实参。”

于是写如下验证程序:
#include <iostream>
using namespace std;

template <class T, class C>
class foo{
public:
T a;
C b;
};

//后续声明提供附加的缺省实参(但是由于模板参数C还没有缺省实参,所以此处应该是错的)
template <class T = int, class C>
class foo;

int main(){
return 0;
}

正如我在程序中标注的,我认为程序应该错误,可是编译成功......(无论vs还是g++都试验过)
请问为什么?

附:vs更加过分,对于下面程序:
#include <iostream>
using namespace std;

template <class T, class C>
class foo{
public:
T a;
C b;
};

//后续声明提供附加的缺省实参(此处应该是正确的)
template <class T, class C = int>
class foo;

int main(int argc, char **argv){
foo<int> f; //编译失败
return 0;
}

这个本应该正确的程序在vs2003上却失败了(在g++上编译成功)。
郁闷......
...全文
438 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
Veiz 2006-06-25
  • 打赏
  • 举报
回复
这么说dm8.48编译器的编译结果也是值得重视的?
Piboye 2006-06-25
  • 打赏
  • 举报
回复
The set of default template-arguments available for use with a template declaration or definition is obtained
by merging the default arguments from the definition (if in scope) and all declarations in scope in the same way default function arguments are (8.3.6).

Very good 和我刚才的想法一样了,merging the default arguments from the definition 就是发生在你使用了默认参数的时候.
Piboye 2006-06-25
  • 打赏
  • 举报
回复
A default template-argument shall not be specified in a friend template declaration.
讲得好啊,又长了点见识^_^

template<typename T>
class good
{};
template <class T, class C,class K>
class foo{
public:
friend
template<typename T=int> //程序出错,friend声明不能有默认实参声明.
class good;
T a;
C b;
};
Piboye 2006-06-25
  • 打赏
  • 举报
回复
有长见识了
nor in the template-parameter-list of the definition of a member of a class template
说的太好了
template <class T, class C,class K>
class foo{
public:
template<typename T=int> //这里不可以有默认参数了
class goo{};
T a;
C b;
};
strangerryf 2006-06-25
  • 打赏
  • 举报
回复
2003版的ISO/IEC14882的14.1提到

9 A default template-argument is a template-argument (14.3) specified after = in a template-parameter. A default template-argument may be specified for any kind of template-parameter (type, non-type, template).
A default template-argument may be specified in a class template declaration or a class template definition.
A default template-argument shall not be specified in a function template declaration or a function template definition, nor in the template-parameter-list of the definition of a member of a class template. A default template-argument shall not be specified in a friend template declaration.

10 The set of default template-arguments available for use with a template declaration or definition is obtained
by merging the default arguments from the definition (if in scope) and all declarations in scope in the same way default function arguments are (8.3.6). [Example:
template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;
is equivalent to
template<class T1 = int, class T2 = int> class A;
—end example]

11 If a template-parameter has a default template-argument, all subsequent template-parameters shall have a
default template-argument supplied. [Example:
template<class T1 = int, class T2> class B; // error
—end example]

c++ primer 3e中的原文是

template <class Type, int size = 1024>
class Buffer;
Subsequent declarations of the class template can provide additional default arguments for the template parameters. As it is the case with default arguments for function parameters, the rightmost uninitialized parameter must be supplied with a default argument before any default argument for a parameter to its left may be supplied. For example:
template <class Type, int size = 1024>
class Buffer;
// ok: default arguments from the two declarations are considered
template <class Type = string , int size>
class Buffer;

lz的问题在于两次写了template <...> class foo{};,去掉前一个再看看。
Piboye 2006-06-25
  • 打赏
  • 举报
回复
默认参数,只有使用时才会暴露它潜在的问题,这可能是程序最隐蔽的BUG
Piboye 2006-06-25
  • 打赏
  • 举报
回复
第一个没有出现错误提示,但并不意味没有错误,而是存在潜在的错误。

模板是使用两次编译的模型,第一次检查的是模板的基本语法构造无误。第二遍才是对于参数有关的构造解释。

C++中规定,模板参数的默认参数要到使用时才实例化。
默认参数在定义时进行 词法检查和名字查找。

问题可能出在大家对书上的说法理解错了。

“类模板的后续声明可以为模板参数提供附加的缺省实参。正如函数参数的缺省实参的情形一样。在向左边的参数提供缺省实参之前,必须首先给最右边未初始化的参数提供缺省实参。”

我估计 "在向左边的参数提供缺省实参之前,必须首先给最右边未初始化的参数提供缺省实参."
这句话翻译出了问题。

我给大家看个例子:

template <class T =double, class C>
class foo;
template <class T, class C=int>
class foo;
foo<> c;
程序正常没有提示出错。
template <class T =double, class C>
class foo;
template <class T=double, class C=int> //程序出错在这
class foo;
foo<> c;

再如:
template <class T =double, class C,class K>
class foo;
template <class T, class C,class K=int>
class foo;
foo<int,int> c;
程序正常

template <class T =double, class C,class K>
class foo;
template <class T, class C,class K=int>
class foo;
foo<int> c;
程序出错


我个人总结是这样的:

默认参数可以在每个声明中定义,但不允许重复定义同一个参数(即使一样的实数),在真正使用默认参数时,所有默认参数都要在表达式的右边,使用的默认参数之间不能有间隔。
Veiz 2006-06-25
  • 打赏
  • 举报
回复
楼主的第一个程序, 我的VC2005和g++3.4.4都能通过编译,只是dm8.48不过编译,
错误提示:Error: trailing parameters must have initializers

第二个程序三个编译器都过了。

《C++ primer》不知道第四版怎么说。

好书应该强调不同编译器的实现不同,

howyougen 2006-06-25
  • 打赏
  • 举报
回复
哦错了

int main(int argc, char **argv){
foo<int> f; //编译失败
return 0;
}

2楼的说得有理
howyougen 2006-06-25
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

template <class T, class C>
class foo{
public:
T a;
C b;
};

//后续声明提供附加的缺省实参(但是由于模板参数C还没有缺省实参,所以此处应该是错的)
template <class T = int, class C>
class foo;

int main(){
return 0;
}

这个我在vc.net上编译不过
  • 打赏
  • 举报
回复
第一个问题,编译器是正确的,如果不服气,可以自己写编译器
第二个问题,
template <class T, class C = int>
class foo;
提到
template <class T, class C>
class foo{
public:
T a;
C b;
};前面就可以了
反正我的vs2005编译过去了
忘了怎么说了,是编译器的模版匹配规则原因
triace_zhang 2006-06-25
  • 打赏
  • 举报
回复
应该还是和编译器里template的实现有关,可以作个实验来看看模板推演的规律:

template <class T, class C>
class foo{
public:
T a;
C b;
void f() {
const type_info& t1 = typeid(a);
cout << "typename of a: " << t1.name() << endl; //这个用来输出实际类型
const type_info& t2 = typeid(b);
cout << "typename of b: " << t2.name() << endl;}
};


template <class T = int, class C>
class foo;

template <class T, class C = float> //必须要加第二个参数的默认类型,不然后面foo实例
//推导是出错。
class foo;

int main(){
foo<double> fo; //只给定第一个参数类型,如果第二个参数没默认类型,则出错。
fo.f();

system("pause");
return 0;
}

可见错误只在实际进行模板参数推演的时候才会被编译器发现。
关于第二个问题,没有vs2003不是很清楚,但是就语法来说应该没错。

64,642

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧