T mymax(const T t1, const T t2)
{
return t1 < t2 ? t2 : t1;
}
template <>//这个去掉就可以了?麻烦解释下
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
int main(int argc, char* argv[])
{
int highest = mymax(5,10);
char c = mymax('a', 'z');
const char* p1 = "hello";
const char* p2 = "world";
const char* p = mymax(p1,p2);
return 0;
}
编译出错:
--------------------Configuration: 模板编程 - Win32 Debug--------------------
Compiling...
模板编程.cpp
C:\Program Files\Microsoft Visual Studio\MyProjects\STL学习\模板编程\模板编程.cpp(24) : error C2912: explicit specialization; 'const char *__cdecl mymax(const char *,const char *)' is not a function template
C:\Program Files\Microsoft Visual Studio\MyProjects\STL学习\模板编程\模板编程.cpp(22) : see declaration of 'mymax'
C:\Program Files\Microsoft Visual Studio\MyProjects\STL学习\模板编程\模板编程.cpp(24) : error C2912: explicit specialization; 'const char *__cdecl mymax(const char *,const char *)' is not a function template
C:\Program Files\Microsoft Visual Studio\MyProjects\STL学习\模板编程\模板编程.cpp(22) : see declaration of 'mymax'
C:\Program Files\Microsoft Visual Studio\MyProjects\STL学习\模板编程\模板编程.cpp(36) : error C2668: 'mymax' : ambiguous call to overloaded function
Error executing cl.exe.
模板编程.exe - 3 error(s), 0 warning(s)
42 个解决方案
#1
template <>//这个去掉就可以了?麻烦解释下
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
把返回值的const去掉看看。
在这里T应该是char* 而不是 const char* 啊。
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
把返回值的const去掉看看。
在这里T应该是char* 而不是 const char* 啊。
#2
你这叫 模板函数和非模板函数的重载,不叫特化
#3
我用mingw的编译器 没错啊。
但是事实上我觉得这个template<> 没什么作用。
template <>//这个去掉就可以了?麻烦解释下
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
但是事实上我觉得这个template<> 没什么作用。
template <>//这个去掉就可以了?麻烦解释下
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
#4
最好不要用函数特化,而是重载。
参见《exceptional c++ style》
参见《exceptional c++ style》
#5
这位大哥就比较瞎搞了 怎么可以把返回值的const去掉呢。。。
#6
是的,这个是重载,我想问的是如果要特化该怎么做?
#7
参见三楼,看出错信息因为楼主用的是VC6,珍爱生命远离VC6。。。
用VC6来玩这些玩不通的。。。
推荐用gcc或者vc9及以上的吧。。。
用VC6来玩这些玩不通的。。。
推荐用gcc或者vc9及以上的吧。。。
#8
7楼的哥们儿,给解释一下吧,难道VC6不支持?或者你给正式的链接我参考参考
#9
刚才没注意看函数的实现,只是看了一下,猜猜错误所在,所以也没在于 去掉const 的后果.
其实要特化的那个函数模版不是lz上面的那个模版。模版原型应该是这个:
其实要特化的那个函数模版不是lz上面的那个模版。模版原型应该是这个:
template <class T>
const T* mymax(const T* t1, const T* t2)
{
return t1 < t2 ? t2 : t1;
}
#10
对!这个就是模板原型,对于char*类型的比较,直接比较的话比较的是指针值
所以在这里特化一下,但是结果却无法编译,为什么呢?或者说应该怎么特化才对?
#11
这才叫特化,但是仍然不推荐。楼主少些了个东西,自己看看:
#include "stdafx.h"
#include <iostream>
template <class T>
T mymax(const T t1, const T t2)
{
return t1 < t2 ? t2 : t1;
}
template <>
const char* mymax<const char*>(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
int main(int argc, char* argv[])
{
int highest = mymax(5,10);
char c = mymax('a', 'z');
const char* p1 = "hello";
const char* p2 = "world";
const char* p = mymax(p1,p2);
return 0;
}
#12
楼主也灌水达到4三角了,咋就要死抱着VC6浪费生命呢?不明白呀。
遇问题多试几个编译器,这也该是基本常识吧。
遇问题多试几个编译器,这也该是基本常识吧。
#13
template <>
const char* mymax <const char*>(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
const char* mymax <const char*>(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
#14
template<class T>
T mymin(T t1, T t2)
{
return (t1<t2?t1:t2);
}
template<>
const char* mymin<>(const char* t1,const char* t2)
{
return(strcmp(t1,t2)<0) ?t1:t2;
}
int main(int argc, char* argv[])
{
cout<<mymin(5,2)<<endl;
cout<<mymin(0.2,0.5)<<endl;
const char p[]="dsfdf";
const char q[]="fgfh";
// cout<<p<<endl;
// cout<<q<<endl;
const char* r;
r=mymin(p,q);
cout<<r<<endl;
return 0;
}
改成这样就可以了!多谢楼上提醒
#15
特化的含义是用一个固定的类型参数去实例化一个模板。
所以有意义的特化必须要和类结合起来才行,比如,类模板的特化。如果是一个普通的函数,给它一个固定的类
型参数,这样的特化就和重载没区别了,就是我前面说的,这里实际上是模板函数和非模板函数的重载。而重载
决议机制会优先匹配非模板函数的函数,如果非要强制使用模板函数,可以在函数名后面加一个空的<>,这样就
是显示的匹配模板函数。但是貌似gcc 4.4不支持这样做...
而特化的时候为什么不需要写template <>,我觉得是因为既然类型参数已经固定了,这个也就没有什么价值
了,写了反而是累赘。就像非特换版本和偏特化的时候必须要写,是因为需要在这里面指定一些模板实例化时
必须的信息。
所以有意义的特化必须要和类结合起来才行,比如,类模板的特化。如果是一个普通的函数,给它一个固定的类
型参数,这样的特化就和重载没区别了,就是我前面说的,这里实际上是模板函数和非模板函数的重载。而重载
决议机制会优先匹配非模板函数的函数,如果非要强制使用模板函数,可以在函数名后面加一个空的<>,这样就
是显示的匹配模板函数。但是貌似gcc 4.4不支持这样做...
而特化的时候为什么不需要写template <>,我觉得是因为既然类型参数已经固定了,这个也就没有什么价值
了,写了反而是累赘。就像非特换版本和偏特化的时候必须要写,是因为需要在这里面指定一些模板实例化时
必须的信息。
#16
大哥,并不是非要抱着VC6不放,我也不喜欢,只是想知道为什么啊?如果说她就是不支持,那么,还有什么不支持?搞明白不是很好?下次一样的问题我就不会再考虑在这上面浪费时间了,您说呢?或者您告诉我现在哪个编译器完全支持C++标准也行。不管怎样,还是非常感谢您的回答,老实说我的很多问题都得到您的解答:)
#17
函数只能全特化,不能特化。
#18
回去看书吧,别误人子弟了...
#19
不能偏特化
#20
嗯,不要误人子弟了。
#21
《exceptional c++ style》
37页
第7条,为什么不特化函数模板。(36页)
37页
第7条,为什么不特化函数模板。(36页)
#22
我看到的说法是函数模板没有偏特化,其实是通过重载实现的。
大家通过讨论来弄清也很好啊,大热的天不要上火啊。
大家通过讨论来弄清也很好啊,大热的天不要上火啊。
#23
函数模板资料较少,只有《exceptional c++ style 》
有详细的讨论,见第7条。
有详细的讨论,见第7条。
#24
去看<C++ Template>的前四章,basic部分就行了
#25
我想知道如果想特化的话怎么做?有什么不好?
猜测一下:是因为参数决议时的问题么?参数会转化,所以有歧义?
这就去看exceptional c++ style......
#26
书上讲:
准则: 记住,函数模板不能偏特化,只能重载。写一个看似函数模板片特化的函数模板实际上是在
写一个单独的主函数模板。
#27
正在看,多谢楼上
#28
别人说的是偏特化不行,而不是全特化不行。
直接用
template<>
说明是一个全特化的开始。
如果要用偏特化的话,在MCD上有珍个Type2Int的手法。
也可以利用类模板加函数来实现
template<typename...>
struct Action
{
static inline void action(...);
};
至于为什么不支持偏特化,其中一个原因就是函数的重载解析和模板解析的混淆。
两者同时都具有参数推断的过程。
可以使用
template<>
void foo<...>()
进行显式的模板
参数匹配
也可以用
template<>
void foo()
进行隐式的参数匹配。
两者各有所长。
全特化和重载在应用起来感觉不大。
但是可以利用全特化降低匹配的优化级,在万不得已的时候实现特殊效果。
#29
lz代码通不过编译,可以明确地说,这是编译器的问题.语法上没有错
#30
未必吧,特化需要“<>”
#31
学习拉!
#32
《c++ primer》第三版10.6,中文版在p425。
#33
书上有这么一句话:“
但是如果模板实参可以从函数参数中推演出来则模板实参的显式特化可以从显式特
化声明中省略
// ok: 模板实参 const char* 可以从参数类型中推演出来
template<> PCC max( PCC , PCC );
”
但是下面举了几个例子,都不满足这个条件。
然后,他说:“
省略显式特化声明中的template<>并不总是错的例如
// 通用模板定义
template <class T>
T max( T t1, T t2 ) { /* ... */ }
// ok: 普通函数定义
const char* max( const char*, const char* );
但是max()的声明并没有声明函数模板特化它只是用与模板实例相匹配的返回值和参
数表声明了一个普通函数声明一个与模板实例相匹配的普通函数并不是个错误
”
const char* max(...)是一个普通函数,不是一个特化版本。
这个只是作为上面那个版本的重载。
根据我自己的经验,如果是类没有"<>",几乎不可能,因为他包含的信息太重要了。
而书的作者只是表达了这样一个观点,“从传入的参数”能推到出来,
那么,什么例子能推到出来?抑或是根本推不出来,必须显示写?
#34
template<>//这个始终不能省略,否则就变成重载版本了。
double max<double>(double, double);//书上的意思说
,有可以省略的情况存在,但是还真没有见过这情况,作者举的例子
都是不能省略的。
#35
template <class T>
const T mymax(const T t1, const T t2)
{
return t1 < t2 ? t2 : t1;
}
加上那个const还更好一些,
因为char mymax(const char t1, const char t2);的返回值是const char,所以去掉的话还支持地更好一些,不明白的话翻一下书吧
const T mymax(const T t1, const T t2)
{
return t1 < t2 ? t2 : t1;
}
加上那个const还更好一些,
因为char mymax(const char t1, const char t2);的返回值是const char,所以去掉的话还支持地更好一些,不明白的话翻一下书吧
#36
...几年前我的blog里面写过...不过那个时候写得比较肤浅.
#37
给个链接吧?
#38
对于template <class T> T mymax(const T t1, const T t2)
做int的特化
template <>
int mymax<int>(int,int);
或
template <>
int mymax<>(int,int);
或
template <>
int mymax(int,int);
都正确.只是后面两种都需要编译器对模板参数的推导
#40
看了半天,懂了一点
#41
这是特化和重载的关系,去掉template<>就是重载,楼主想要特化成const char*的话,函数名和函数参数列表之间要加<const char*>
#42
应该不会去连接那个 obj 文件,所以找不到 对应的函数定义。
#1
template <>//这个去掉就可以了?麻烦解释下
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
把返回值的const去掉看看。
在这里T应该是char* 而不是 const char* 啊。
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
把返回值的const去掉看看。
在这里T应该是char* 而不是 const char* 啊。
#2
你这叫 模板函数和非模板函数的重载,不叫特化
#3
我用mingw的编译器 没错啊。
但是事实上我觉得这个template<> 没什么作用。
template <>//这个去掉就可以了?麻烦解释下
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
但是事实上我觉得这个template<> 没什么作用。
template <>//这个去掉就可以了?麻烦解释下
const char* mymax(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
#4
最好不要用函数特化,而是重载。
参见《exceptional c++ style》
参见《exceptional c++ style》
#5
这位大哥就比较瞎搞了 怎么可以把返回值的const去掉呢。。。
#6
是的,这个是重载,我想问的是如果要特化该怎么做?
#7
参见三楼,看出错信息因为楼主用的是VC6,珍爱生命远离VC6。。。
用VC6来玩这些玩不通的。。。
推荐用gcc或者vc9及以上的吧。。。
用VC6来玩这些玩不通的。。。
推荐用gcc或者vc9及以上的吧。。。
#8
7楼的哥们儿,给解释一下吧,难道VC6不支持?或者你给正式的链接我参考参考
#9
刚才没注意看函数的实现,只是看了一下,猜猜错误所在,所以也没在于 去掉const 的后果.
其实要特化的那个函数模版不是lz上面的那个模版。模版原型应该是这个:
其实要特化的那个函数模版不是lz上面的那个模版。模版原型应该是这个:
template <class T>
const T* mymax(const T* t1, const T* t2)
{
return t1 < t2 ? t2 : t1;
}
#10
对!这个就是模板原型,对于char*类型的比较,直接比较的话比较的是指针值
所以在这里特化一下,但是结果却无法编译,为什么呢?或者说应该怎么特化才对?
#11
这才叫特化,但是仍然不推荐。楼主少些了个东西,自己看看:
#include "stdafx.h"
#include <iostream>
template <class T>
T mymax(const T t1, const T t2)
{
return t1 < t2 ? t2 : t1;
}
template <>
const char* mymax<const char*>(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
int main(int argc, char* argv[])
{
int highest = mymax(5,10);
char c = mymax('a', 'z');
const char* p1 = "hello";
const char* p2 = "world";
const char* p = mymax(p1,p2);
return 0;
}
#12
楼主也灌水达到4三角了,咋就要死抱着VC6浪费生命呢?不明白呀。
遇问题多试几个编译器,这也该是基本常识吧。
遇问题多试几个编译器,这也该是基本常识吧。
#13
template <>
const char* mymax <const char*>(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
const char* mymax <const char*>(const char* t1,const char* t2)
{
return (strcmp(t1,t2) < 0) ? t2 : t1;
}
#14
template<class T>
T mymin(T t1, T t2)
{
return (t1<t2?t1:t2);
}
template<>
const char* mymin<>(const char* t1,const char* t2)
{
return(strcmp(t1,t2)<0) ?t1:t2;
}
int main(int argc, char* argv[])
{
cout<<mymin(5,2)<<endl;
cout<<mymin(0.2,0.5)<<endl;
const char p[]="dsfdf";
const char q[]="fgfh";
// cout<<p<<endl;
// cout<<q<<endl;
const char* r;
r=mymin(p,q);
cout<<r<<endl;
return 0;
}
改成这样就可以了!多谢楼上提醒
#15
特化的含义是用一个固定的类型参数去实例化一个模板。
所以有意义的特化必须要和类结合起来才行,比如,类模板的特化。如果是一个普通的函数,给它一个固定的类
型参数,这样的特化就和重载没区别了,就是我前面说的,这里实际上是模板函数和非模板函数的重载。而重载
决议机制会优先匹配非模板函数的函数,如果非要强制使用模板函数,可以在函数名后面加一个空的<>,这样就
是显示的匹配模板函数。但是貌似gcc 4.4不支持这样做...
而特化的时候为什么不需要写template <>,我觉得是因为既然类型参数已经固定了,这个也就没有什么价值
了,写了反而是累赘。就像非特换版本和偏特化的时候必须要写,是因为需要在这里面指定一些模板实例化时
必须的信息。
所以有意义的特化必须要和类结合起来才行,比如,类模板的特化。如果是一个普通的函数,给它一个固定的类
型参数,这样的特化就和重载没区别了,就是我前面说的,这里实际上是模板函数和非模板函数的重载。而重载
决议机制会优先匹配非模板函数的函数,如果非要强制使用模板函数,可以在函数名后面加一个空的<>,这样就
是显示的匹配模板函数。但是貌似gcc 4.4不支持这样做...
而特化的时候为什么不需要写template <>,我觉得是因为既然类型参数已经固定了,这个也就没有什么价值
了,写了反而是累赘。就像非特换版本和偏特化的时候必须要写,是因为需要在这里面指定一些模板实例化时
必须的信息。
#16
大哥,并不是非要抱着VC6不放,我也不喜欢,只是想知道为什么啊?如果说她就是不支持,那么,还有什么不支持?搞明白不是很好?下次一样的问题我就不会再考虑在这上面浪费时间了,您说呢?或者您告诉我现在哪个编译器完全支持C++标准也行。不管怎样,还是非常感谢您的回答,老实说我的很多问题都得到您的解答:)
#17
函数只能全特化,不能特化。
#18
回去看书吧,别误人子弟了...
#19
不能偏特化
#20
嗯,不要误人子弟了。
#21
《exceptional c++ style》
37页
第7条,为什么不特化函数模板。(36页)
37页
第7条,为什么不特化函数模板。(36页)
#22
我看到的说法是函数模板没有偏特化,其实是通过重载实现的。
大家通过讨论来弄清也很好啊,大热的天不要上火啊。
大家通过讨论来弄清也很好啊,大热的天不要上火啊。
#23
函数模板资料较少,只有《exceptional c++ style 》
有详细的讨论,见第7条。
有详细的讨论,见第7条。
#24
去看<C++ Template>的前四章,basic部分就行了
#25
我想知道如果想特化的话怎么做?有什么不好?
猜测一下:是因为参数决议时的问题么?参数会转化,所以有歧义?
这就去看exceptional c++ style......
#26
书上讲:
准则: 记住,函数模板不能偏特化,只能重载。写一个看似函数模板片特化的函数模板实际上是在
写一个单独的主函数模板。
#27
正在看,多谢楼上
#28
别人说的是偏特化不行,而不是全特化不行。
直接用
template<>
说明是一个全特化的开始。
如果要用偏特化的话,在MCD上有珍个Type2Int的手法。
也可以利用类模板加函数来实现
template<typename...>
struct Action
{
static inline void action(...);
};
至于为什么不支持偏特化,其中一个原因就是函数的重载解析和模板解析的混淆。
两者同时都具有参数推断的过程。
可以使用
template<>
void foo<...>()
进行显式的模板
参数匹配
也可以用
template<>
void foo()
进行隐式的参数匹配。
两者各有所长。
全特化和重载在应用起来感觉不大。
但是可以利用全特化降低匹配的优化级,在万不得已的时候实现特殊效果。
#29
lz代码通不过编译,可以明确地说,这是编译器的问题.语法上没有错
#30
未必吧,特化需要“<>”
#31
学习拉!
#32
《c++ primer》第三版10.6,中文版在p425。
#33
书上有这么一句话:“
但是如果模板实参可以从函数参数中推演出来则模板实参的显式特化可以从显式特
化声明中省略
// ok: 模板实参 const char* 可以从参数类型中推演出来
template<> PCC max( PCC , PCC );
”
但是下面举了几个例子,都不满足这个条件。
然后,他说:“
省略显式特化声明中的template<>并不总是错的例如
// 通用模板定义
template <class T>
T max( T t1, T t2 ) { /* ... */ }
// ok: 普通函数定义
const char* max( const char*, const char* );
但是max()的声明并没有声明函数模板特化它只是用与模板实例相匹配的返回值和参
数表声明了一个普通函数声明一个与模板实例相匹配的普通函数并不是个错误
”
const char* max(...)是一个普通函数,不是一个特化版本。
这个只是作为上面那个版本的重载。
根据我自己的经验,如果是类没有"<>",几乎不可能,因为他包含的信息太重要了。
而书的作者只是表达了这样一个观点,“从传入的参数”能推到出来,
那么,什么例子能推到出来?抑或是根本推不出来,必须显示写?
#34
template<>//这个始终不能省略,否则就变成重载版本了。
double max<double>(double, double);//书上的意思说
,有可以省略的情况存在,但是还真没有见过这情况,作者举的例子
都是不能省略的。
#35
template <class T>
const T mymax(const T t1, const T t2)
{
return t1 < t2 ? t2 : t1;
}
加上那个const还更好一些,
因为char mymax(const char t1, const char t2);的返回值是const char,所以去掉的话还支持地更好一些,不明白的话翻一下书吧
const T mymax(const T t1, const T t2)
{
return t1 < t2 ? t2 : t1;
}
加上那个const还更好一些,
因为char mymax(const char t1, const char t2);的返回值是const char,所以去掉的话还支持地更好一些,不明白的话翻一下书吧
#36
...几年前我的blog里面写过...不过那个时候写得比较肤浅.
#37
给个链接吧?
#38
对于template <class T> T mymax(const T t1, const T t2)
做int的特化
template <>
int mymax<int>(int,int);
或
template <>
int mymax<>(int,int);
或
template <>
int mymax(int,int);
都正确.只是后面两种都需要编译器对模板参数的推导
#39
#40
看了半天,懂了一点
#41
这是特化和重载的关系,去掉template<>就是重载,楼主想要特化成const char*的话,函数名和函数参数列表之间要加<const char*>
#42
应该不会去连接那个 obj 文件,所以找不到 对应的函数定义。