模板参数顺序问题

adie20018u8 2006-09-29 10:06:27
boost.python:

Class template class_<T, Bases, HeldType, NonCopyable>
Creates a Python class associated with the C++ type passed as its first parameter. Although it has four template parameters, only the first one is required. The three optional arguments can actually be supplied 【in any order】; Boost.Python determines the role of the argument from its type.

boost.spirit

Order of parameters
As of v1.8.0, the ScannerT, ContextT and TagT can be specified 【in any order】. If a template parameter is missing, it will assume the defaults. Examples:

rule<> rx1;
rule<scanner<> > rx2;
rule<parser_context<> > rx3;
rule<parser_context<>, parser_address_tag> rx4;
rule<parser_address_tag> rx5;
rule<parser_address_tag, scanner<>, parser_context<> > rx6;
rule<parser_context<>, scanner<>, parser_address_tag> rx7;


他们是如何做到模板参数顺序无关这点的? 我看过源代码,没弄明白到底怎么实现的,请高手指教。
...全文
257 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
adintr 2006-09-29
  • 打赏
  • 举报
回复
看了一下 boost.spirit 的源代码,
rule 把 3 个模板参数都交给 rule_base 了, rule_base 通过如下这三个 typedef 来萃取三种类型的型别:

typedef typename impl::get_scanner<T0, T1, T2>::type scanner_t;
typedef typename impl::get_context<T0, T1, T2>::type context_t;
typedef typename impl::get_tag<T0, T1, T2>::type tag_t;

这 3 个 get 提供了一个基类和默认值,然后通过 get_param 来完成工作:

template <typename T0, typename T1, typename T2>
struct get_context
{
typedef typename get_param<
parser_context_base, parser_context<>, T0, T1, T2>::type
type;
};

其余两个的实现差不多, get_param 逐一判断第 4, 5,6 三个参数是否是从第一参数继承而来的,如果是就返回这个参数,否则的化返回第二个参数:

template <typename BaseT, typename DefaultT
, typename T0, typename T1, typename T2>
struct get_param
{
typedef typename mpl::if_<
is_base_and_derived<BaseT, T0>
, T0
, typename mpl::if_<
is_base_and_derived<BaseT, T1>
, T1
, typename mpl::if_<
is_base_and_derived<BaseT, T2>
, T2
, DefaultT
>::type
>::type
>::type type;
};

所以, rule 三个策略类的模板参数可以交换顺序是因为他们有不同的基类,parser_context_base, parser_tag_base,scanner_base。
如果你给出的类不是从以上这三个中的一个派生的,它就无能为力了,给出的参数会被忽略掉。

OOPhaisky 2006-09-29
  • 打赏
  • 举报
回复
建议:如果不想深入学习泛型,不要在这上花太多时间,累啊
OOPhaisky 2006-09-29
  • 打赏
  • 举报
回复
模版元编程的东西,很复杂的。
偏特化 + typedef + 递归...
这类东西很让人头疼啊^_^
jerry 2006-09-29
  • 打赏
  • 举报
回复
使用偏特化
adintr 2006-09-29
  • 打赏
  • 举报
回复
是顺序无关了,但默认参数怎么办呢?

template <typename T1 = DefaultCreator, typename T2 = DefaultDestorior>
class A: public T1, public T2 { ... }

A<MyDestorior, MyCreator> a1; // 很好
A<MyDestorior> a2; // 怎么办?

------------------------------------------------
恩,这确实是个问题,看来这个办法还是行不通
taodm 2006-09-29
  • 打赏
  • 举报
回复
楼主既然要做库,那么就只有研究Boost源码最直接了,偶是答不了你这个问题的了。
如果楼主暂时不做库,就不要多研究,需要学习的东西太多了,不必于此多花时间。
祝好!
adie20018u8 2006-09-29
  • 打赏
  • 举报
回复
template <typename T1, typename T2>
class A : public T1, public T2
{
};

这样不就顺序无关了吗?

--------------------------------------------
是顺序无关了,但默认参数怎么办呢?

template <typename T1 = DefaultCreator, typename T2 = DefaultDestorior>
class A: public T1, public T2 { ... }

A<MyDestorior, MyCreator> a1; // 很好
A<MyDestorior> a2; // 怎么办?
adie20018u8 2006-09-29
  • 打赏
  • 举报
回复
用模板元编程MPL当然可以做到这一点,就是实在代码太复杂了。
就不要试图弄明白了吧。
只有做“库”的人才需要掌握这个技能。
--------------------------------------------------------

~~你怎么知道我不是做库的? 或者我将来也不会做库?
taodm 2006-09-29
  • 打赏
  • 举报
回复
正交分解只是理想。看MCD的smartptr实现就知道,它没能做到正交,所以它也就很难用继承法来实现得与模板参数顺序无关的。
模板参数顺序无关带来的便利性实在也很小,大家都早就习惯了C++的强类型,按顺序写参数。
MCD的作者所以也认为这不是需求,所以没有涉及讨论。
用typelist方法来实现的话,要之就是每个策略类提供可萃取的类型信息,对typelist遍历(递归)搜索这个信息即可。
sinall 2006-09-29
  • 打赏
  • 举报
回复
回复人:adintr(www.adintr.com)(其实,我不是一个演员) ( 五级(中级)) 信誉:100 2006-09-29 10:56:00 得分:0

我想这些顺序无关的模板参数大多是一些策略类,一般来说策略的分解都是正交的,所以菱形继承,同名函数之类是可以避免的。
——————————————————————————————————————————
支持这个观点。
比如你需要一个这样的类A,和A相关的类型如下:
A::_T1,A::_T2
那么,
template <typename T1, typename T2>
class A : public T1, public T2
{
};
T1和T2只需要下面的类:
A1,A2并且A1::_T1,A2::_T2
或者
A1,A2并且A1::_T2,A2::_T1
adintr 2006-09-29
  • 打赏
  • 举报
回复
怎么会没有需求呢?只是它没有实现而已,比如它的 SingletonHolder 模板类就有 3 个策略类作为参数,如果能让这三个参数顺序无关,使用起来是方便很多的。

Typelist 如何能实现这个功能? 给个例子看看。
taodm 2006-09-29
  • 打赏
  • 举报
回复
《Modern C++ Design》没有这个模板参数顺序无关的需求,但是用他提供的type_list思想可以实现这个功能。《元编程》正试图看,还不知道它讲没有。
adintr 2006-09-29
  • 打赏
  • 举报
回复
我想这些顺序无关的模板参数大多是一些策略类,一般来说策略的分解都是正交的,所以菱形继承,同名函数之类是可以避免的。

另, 《Modern C++ Design》 有讲顺序无关的模板参数么? 哪一章?
taodm 2006-09-29
  • 打赏
  • 举报
回复
to adintr(www.adintr.com)(其实,我不是一个演员)
呵呵,蛮好的思路。不过,棱形继承问题,同名函数重载解析问题。。。。
要能形成真正的可用库,还有很远呀。

如果想搞清楚(或者说搞晕),看《Modern C++ Design》等元编程的书吧。
adintr 2006-09-29
  • 打赏
  • 举报
回复
template <typename T1, typename T2>
class A : public T1, public T2
{
};

这样不就顺序无关了吗?
123ppmove 2006-09-29
  • 打赏
  • 举报
回复
学习ing;
taodm 2006-09-29
  • 打赏
  • 举报
回复
用模板元编程MPL当然可以做到这一点,就是实在代码太复杂了。
就不要试图弄明白了吧。
只有做“库”的人才需要掌握这个技能。
adintr 2006-09-29
  • 打赏
  • 举报
回复
知道了上面的原理,我们可以用一个模板参数来获得和三个模板参数一样的效果。

struct MyRulePolicy:
public parser_context_base,
public parser_tag_base,
public scanner_base
{
...
}

rule<MyRulePolicy>
等价于
rule<MyRulePolicy, MyRulePolicy, MyRulePolicy>
等价于
rule<MyContext, MyTag, MyScanner>

64,654

社区成员

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

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