C++ “真实世界的例子是什么?”;指向成员的智能指针“;?

C++ “真实世界的例子是什么?”;指向成员的智能指针“;?,c++,pointers,operator-overloading,operators,smart-pointers,C++,Pointers,Operator Overloading,Operators,Smart Pointers,为了澄清英语中可能存在的优先歧义:我们采用的是“smart(指针指向成员)”,而不是“smart指针指向成员” 我会将指向成员的智能指针定义为带有操作符->*(T*lhs,X rhs)重载的类X Scott Meyers在他的文章中只简要地提到了指向成员的智能指针,因为在当时(1999年),对于raw指向成员的指针来说,具体问题已经足够困难了(旁注:后者是通过lambdas优雅地解决的) 无论如何,斯科特·迈尔斯在脚注中写道: 在写了这篇文章的草稿后不久,我的一个顾问 客户向我展示了一个问题,通

为了澄清英语中可能存在的优先歧义:我们采用的是“smart(指针指向成员)”,而不是“smart指针指向成员”

我会将指向成员的智能指针定义为带有
操作符->*(T*lhs,X rhs)
重载的类X

Scott Meyers在他的文章中只简要地提到了指向成员的智能指针,因为在当时(1999年),对于raw指向成员的指针来说,具体问题已经足够困难了(旁注:后者是通过lambdas优雅地解决的)

无论如何,斯科特·迈尔斯在脚注中写道:

在写了这篇文章的草稿后不久,我的一个顾问 客户向我展示了一个问题,通过向成员提供智能指针自然解决了这个问题。我也很惊讶

我试图找到这样一个自然智能指针指向成员的例子。 但我自己也找不到任何东西,在线搜索也没有发现我在寻找什么

你知道现实世界中“智能指针指向成员”的例子吗

编辑: 我没有寻找任何
->*
过载(就像某些EDSL所做的那样)。
针对语义类似于内置
->*
的示例,我上面的定义明确要求
lhs
为原始指针。

您有一个布局引擎,可以进行90度旋转(高度和宽度交换)

使用智能成员指针,您可以使
(foo->*x)
(foo->*y)
交换意义。同样的智能
x
y
可以处理不同的不相关类型的数据(矩形、点、向量),甚至是您不拥有的类型

template<class F>
struct smart_pm_t {
  F f;
  template<class T>
  friend decltype(auto) operator->*(T* t, smart_pm_t const& self ) {
    return self.f(t);
  }
};

template<class F>
smart_pm_t<F> smart_pm( F f ) { return {std::move(f)}; }

auto x = smart_pm( [](auto* t)->decltype(auto) noexcept { return t->x; } );
auto y = smart_pm( [](auto* t)->decltype(auto) noexcept { return t->y; } );
vs

水平或垂直地解决问题

这是实际生产代码中的实际(简化)用例,它减少了代码重复并消除了一大堆错误,因为我们只需修复代码一次

右边的普通成员指针有一个问题,我们必须传递一整套成员指针,每种类型在左边工作一个


实际上,我们编写了一个编译时多态成员指针。

Good call with the Dismusification Premission.cppreference提到它是“。事实上,boost.phoenix中的角色使用了它。它在EDSL中更为常见,例如cpp.react。”如果我们可以询问他的咨询客户;)即使在这里,这也是一个有趣的例子。但是它们都不是cpp中真正的智能指针。react示例
->*
不用作通过指向成员的指针进行访问。他们只是在EDSL中使用它,可以选择任何其他二进制运算符。它与我的定义不匹配,因为
lhs
不是原始指针。感谢@Yakk提供的有见地的示例。也许我遗漏了什么,但在我看来,这就像lambda调用周围的语法噪音:因为
do_layout
无论如何都必须是一个模板,你可以只做
auto-get_x=[](auto*t)->decltype(auto){return t->x;}
(注意lambda与您的相同),使用
get\ux(data)
调用
do\u布局(data,get\ux,get\u y)
而不是
data->*x
内部,从而更容易实现相同的功能。或者可以通过扩展示例(您提到它是简化的)来激发使用
->*
的动机吗?重载
->*
而不是将访问器作为lambda传递的动机是什么?如果你能解释一下,那就太好了@Yakk@tobi我不知道你在问什么。是的,每一行代码都可以以不同的方式重写<对于任何操作员
+
f(b)(a)
,code>a+b始终可以重写为
f(a,b)
。在这种情况下,
x
表现为成员指针,使用成员指针语法是有意义的。重载
+
很常见,但很少使用
->*
(即使没有重载)。那么你写额外代码的故事是什么?历史(您以前有原始内存PTR和重构)?原始成员PTR和智能成员PTR使用相同的算法?我只是好奇。。。
do_layout( data, x, y );
do_layout( data, y, x );