【<专题讨论>[模板模式]<2>】成员模板和返回值重载

xueweizhong 2003-10-29 02:19:30
加精
(1)成员模板
提供了一种类的成员函数的无限可能性
(2)返回值重载
使得我们的表达式调用语义依赖与使用上下文。

下面是我写的一个例子:

#include <windows.h>
#include <exception>

struct Return_overload
{
FARPROC data;

Return_overload(FARPROC data_)
: data(data_)
{}

template <typename T>
operator T () const
{
return (T)data;
}
};

struct Library
{
HMODULE handle;
Library(char const* name)
: handle(LoadLibrary(name))
{
if (handle == NULL)
throw std::bad_exception();
}
~Library()
{
FreeLibrary(handle);
}

Return_overload get_func(char const* name)
{
return GetProcAddress(handle, name);
}
};

int main()
{
Library lib("c:\\test.dll");
if (int (*show)(const char*)
= lib.get_func("_db2_show_sql_form")
)
show("c:\\db2sql\\define.ini");

// new :

// old :
// int (*show)(const char*) =
// (int (*)(const char*))GetProcAddress(...);
^^^^^^^^^^^^^^^^^^^^^

// int (*show)(const char*) =
// lib.get_func("_db2_show_sql_form");
// ^^^^^^^^^^^^^^^^^^^^^
// 此处没有了上面的返回值类型转换。

return 0;
}

注意^^^^^^^^^^部分,由于我们的成员模板和返回值重载
的使用,使得我们可以少写一个类型转换。

希望大家:
(1)探讨一下这个机制的一般化
(2)提供一些其他的应用代码例子
(3)弊端
我们在这里共同探讨一下,共同进步。
...全文
146 66 打赏 收藏 转发到动态 举报
写回复
用AI写文章
66 条回复
切换为时间正序
请发表友善的回复…
发表回复
lyr311 2003-12-29
  • 打赏
  • 举报
回复
薛兄可有QQ?很想拜你为师啊???
lyr311 2003-12-29
  • 打赏
  • 举报
回复
我说的是函数模板,不是模板函数哦?可以吗???
xueweizhong 2003-12-29
  • 打赏
  • 举报
回复
》to lyr311(老刘:CSDN上瘾只为学习C++!)
大家共同进步,各有所长,相互学习。
xueweizhong 2003-12-28
  • 打赏
  • 举报
回复
>to lyr311(老刘:CSDN上瘾只为学习C++!) :
》类模板可以成为另外一个类模板的成员,即为成员模板,
》那么,为什么函数模板不能成为一
》个类的成员呢???

1 C++ 存在函数模板成员

2 不知道你具体想问什么?请说一下。
mechgoukiteng 2003-12-28
  • 打赏
  • 举报
回复
过分追求template技巧不太好吧

感觉上用到ACE那样比较符合工程需要
lyr311 2003-12-28
  • 打赏
  • 举报
回复
这个帖子这么久没人回答啊。
我只想问各位高手一句:
类模板可以成为另外一个类模板的成员,即为成员模板,那么,为什么函数模板不能成为一个类的成员呢???
LoveCreatesBeauty 2003-11-25
  • 打赏
  • 举报
回复
学习
xueweizhong 2003-11-24
  • 打赏
  • 举报
回复
>to babysloth(小懒虫虫)
既然是路过的前辈高手,也请指点一二。
能提一下你们当时发生的问题吗?
让我们这些后来者也学习一下.....
playmud 2003-11-23
  • 打赏
  • 举报
回复
3颗星的这个说得比较有道理,如果弄出来一个全部泛型的东西,输入返回都不用考虑类型的话,效率肯定会降低,而且容易出现bug,包含的东西越多,考虑不全的地方就越多,其中的转化更是成梯形增长,实用性不会很强,但是从纯粹的技术角度来讲的话,还是比较有积极意义的。以上是一个菜鸟的看法!
babysloth 2003-11-23
  • 打赏
  • 举报
回复
小弟我只是顺便过路啦,呵呵,好久没来了。
这个类似的讨论记得两年前bugn在smiling上有过讨论,
当时似乎是要做一个template化的add,为了返回值折腾了很久,
后来觉得完全是在折腾自己,何苦:-)
短歌如风 2003-11-23
  • 打赏
  • 举报
回复

想不到连大名鼎鼎的“懒虫”都惊动了……

后来的讨论我一直没有插嘴,因为感觉把握不住讨论的中心了。我再从一开始的问题开始吧。

  主题是“返回值重载”,这是一个很有意思的话题。我们在C++中可以写重载函数,要求不同的重载版本参数列表不同:
double min(double, double);
int min(int, int);
但是不允许参数列表相同但返回类型不同的重载:
double random();
int random();
这样是不合法的。在Object Pascal中的方法是有一个整数参数的random返回整数(参数是范围),无参数的返回浮点数。

而使用一个“中间对象”的方法其实是可以实现“按返回值重载”的,但事实上重载的不是函数本身,而是类的类型转换操作符。因此,我觉得函数本身也不应该进行计算,只完成对象的构造,把计算改到类型转换操作符中,然后在类定义中为不同类型的转换分别实现不同的操作,这样才能完成重载的真正含义。

歧义当然是可能遇到的,在真正的函数重载机制中同样会遇到歧义,这时我们就要用显式类型转换来解决。只要在“返回值重载”的机制中也能够用显式指定的方法了消除所有歧义,我觉得就已经成功了。
babysloth 2003-11-23
  • 打赏
  • 举报
回复
很久没来了,看到这里讨论满热烈,随便说了两句,见谅。

在一年前的一个project里,我做过一个和你帖子描述的几乎一模一样的东西,一个封装了DLL载入的类,自动转换函数指针类型。自己用起来是很爽,但是同一个team的未必认同。返回值根据类型不同而不同,很容易引起理解上的混乱和实际使用的错误,我更情愿多写一个类型转换:-)

不过这个就扯远了,不好意思。
xueweizhong 2003-11-22
  • 打赏
  • 举报
回复
因为上下文很有限,
所以这里的结论可能回显得粗浅而且不太正确。
比如下面的这个:

1:最多只能提供一个非模板的类型转换函数

虽然在我们的上下文中:
 不允许
struct Foo
{
operator char () const;
operator int () const;
};
同时出现,但却允许出现
struct A;
struct Foo
{
operator char () const;
operator A () const;
};
只要这里的类A和char不可能转换到共同的目标。


> babysloth(小懒虫虫) (★★★)
如果你觉得有些非常不妥的地方,请具体的说明一下。
这样,我会非常感谢。
关于上贴的观点描述,理解上有些模糊,请指教...




babysloth 2003-11-22
  • 打赏
  • 举报
回复
多写一个类型不是什么大错……按你这样想,stl里那些functor通通可以把类型参数扔了
xueweizhong 2003-11-21
  • 打赏
  • 举报
回复
重新提一下原来的东西:

(1)成员模板
提供了一种类的成员函数的无限可能性
(2)返回值重载
使得我们的表达式调用语义依赖与使用上下文。

现在我们得到了一些结论:

1:最多只能提供一个非模板的类型转换函数

2:如果要使用类型转换函数模板,则
不能出现非模板的类型转换

3: 如果要使类型转换函数模板和非模板版本共存,
可增加一个中间层:
成员模板函数,通过这个成员模板函数和其
相应的非模板成员函数重载达到效果。

4:any_cast可以代替类型的重复书写,含义上更明确些:
Target target = (Target)source; --->
Target target = any_cast(source);

5: auto_ptr是一个坎,编译器的错误描述也比较模糊。
转换多了的确是会导致增加代码理解难度。

呵呵,期望大家再补充一些....
xueweizhong 2003-11-20
  • 打赏
  • 举报
回复
又回去看了plainsong的代码变化:

struct return_overload
{
template<typename T>
operator T() const;

operator unsigned int() const;
// ----------#1
};

----->

struct return_overload
{
private:
template <typename T>
T do_type_cast(T*) const;

template <>
unsigned int do_type_cast(unsigned int *) const;

public:
template<typename T>
operator T() const
{
return do_type_cast((T*)0);
}
};

前面那个版本中如果#1是特殊化,将挑战一些编译器的能力。
而不过不是特殊化,而是重载,将导致模板转换函数被永远
屏蔽(具体原因看前面几贴)。

现在我们清楚了这些之后,回过头来看看后一个版本,
呵呵,实现了同样的功能,而且提供一个中间层后,降低了
对编译器的挑战性。

呵呵,果然是个好注意。
aflyinghorse 2003-11-12
  • 打赏
  • 举报
回复
xueweizhong(薛卫忠)
我没有在STD98中找到这样的解释,我是在more effective c++里看到的,
是智能指针那个条款。
xueweizhong 2003-11-12
  • 打赏
  • 举报
回复
>to aflyinghorse()
非常感谢。关于模板方面的事情我一向不太信任Scott Meyer.
所以把more effective c++忽略了,呵呵。

不过我突然又想起些什么,导致我认为你的观点是正确的,
于是我去翻阅了STD98中的
13.3.3.1 Best Viable Function
这一小节。呵呵,有些原理我本是知道的,在碰到实际代码时
却迷糊了一下,下面是说明你那句话的“标准原文”:

Given these defintions, .. viable F1 is .. better
vialbe F2 ...., and then
--...
--F1 is non-template function and F2 is a template function specialization
--...

在我们的例子中两种转换都是user-defined conversion,不可比较好坏,
但加上上面这一条后,呵呵,模板被降为“二等公民”了。
xueweizhong 2003-11-11
  • 打赏
  • 举报
回复
如果是的话,还请aflyinghorse多多指教。
xueweizhong 2003-11-11
  • 打赏
  • 举报
回复
>to aflyinghorse()
"因为编译器在把一个类对象转换为其他类型时会先查找这个类有没有转换
函数,如果没找到才去看是否有成员模板,如果有就把它实例化一个合适
的版本。"

描述这个东东的东西在STD的哪个部分出现?
还是....如果STD98中没说的话,很怀疑其正确性...
加载更多回复(46)

64,648

社区成员

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

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