【问题标题】:C++ - How do placeholders work (particularly in boost::type_erasure)?C++ - 占位符如何工作(特别是在 boost::type_erasure 中)?
【发布时间】:2015-11-03 22:36:07
【问题描述】:

我正在尝试了解类型擦除技术,正如 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 源库中常见的规范用法吗?

提前感谢您对此的看法!

【问题讨论】:

  • 标准保留有两个下划线 (__) 或以一个下划线和一个大写字母 (_A) 开头的名称。 se__lf_Self 保留,但 _self 不保留。
  • 命名空间...命名空间
  • 每个问题一个问题!

标签: c++ boost


【解决方案1】:

一般来说,占位符只是可以在模板元编程中“切换”的独特类型。

通常,当有多个相同“种类”的占位符时,它们是相关的,例如:

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&lt;something, ..., my_placeholder_t&lt;2&gt;, my_placeholder_t&lt;1&gt;&gt;(见Expression templates)。

在稍后阶段,这些类型将被“解释”,例如当你这样做时:

do_action(et, make_tuple("ignored!", "something", 42));

do_action 的实现可以解释占位符以从该元组中获取其对应的元素,例如这就是bind 库函数(std::bind、boost::bind、boost::lambda::bind、boost::phoenix::bind、boost::mpl::bind...)都倾向于做。


在Boost TypeErasure中,占位符_self主要用于指定成员函数concept规范中this参数的限定。

【讨论】:

    猜你喜欢
    • 2012-03-14
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-29
    • 1970-01-01
    • 2023-01-14
    相关资源
    最近更新 更多