我正在尝试理解类型擦除技术,如所讨论的here并在adobe :: poly和Boost :: TypeErasure中实现。不幸的是,我似乎错过了对占位符的基本理解;我目前正在努力理解boost文档(here)中的以下代码:
std::vector<int> vec;
any<has_push_back<_self, int>, _self&> c(vec);
我的问题如下:
1)我相信我已经看过几个占位符的例子 - 在lambdas,Boost MPL等中。似乎有一个约定用一个前导下划线指定这些。我的理解是,根据标准,保留带有前导下划线的标识符,至少在文件/全局范围内。如果这是正确的,那表明占位符是在某处定义的。那么“_self”占位符定义在哪里以及如何定义? (我在图书馆看到了一个宣言,但那就是全部 - 没有实施。是否需要这一切?)
2)据推测,每个库都定义了它们的占位符 - 但它们通常具有相同的名称(例如,“_ 1”,“_ 2”,......)。因此,当在翻译单元中一起使用多个库时,开发人员通常需要明确限定用法以避免歧义/冲突?或ADL以某种方式减轻这种情况?最好的做法是明确限定占位符,还是避免过度“语法噪音”?
3)在上面的代码中,似乎在“any”的实例化过程中,“_ self”被std :: vector替换。这是以某种方式从这个变量声明/初始化语句中隐式推断出来的吗? (也许通过ctor模板???)如果没有,这是如何工作的?
4)这些占位符是否始终是模板参数的类型说明符?这是元编程/ lambda源库中常见的规范用法吗?
提前感谢您对此的看法!
答案 0 :(得分:0)
一般来说,占位符只是可以在模板元编程中“切换”的唯一类型。
通常,当存在多个相同“种类”的占位符时,它们是相关的,例如:
template <int N>
struct my_placeholder_t {
enum { value = N };
};
typedef my_placeholder_t<0> _0;
typedef my_placeholder_t<1> _1;
typedef my_placeholder_t<2> _2;
...
这种关系只会使编写代码变得更容易,但对最终用户来说无关紧要:
typedef /*implementation-defined*/ _0;
typedef /*implementation-defined*/ _1;
typedef /*implementation-defined*/ _2;
...
实施将在稍后阶段使用占位符。占位符通常以类型编码:
auto et = foo(_2, _1);
将导致例如template_expr<something, ..., my_placeholder_t<2>, my_placeholder_t<1>>
(见Expression templates)。
在稍后阶段,这些类型将被“解释”,例如,当你这样做时:
do_action(et,make_tuple(“忽略!”,“某事”,42));
do_action
的实现可以解释占位符以从该元组中获取相应的元素,例如这就是bind
库函数(std :: bind,boost :: bind,boost :: lambda :: bind,boost :: phoenix :: bind,boost :: mpl :: bind ...)全部倾向于做。
在Boost TypeErasure中,占位符_self
主要用于指定成员函数概念规范中this
个参数的限定。