问题标签 [customization-point]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
559 浏览

c++ - 为什么 std::swap 不使用交换习语?

由于正确使用 std::swap 是:

它有点冗长,但它确保如果 a,b 定义了更好的交换,它就会被选中。

所以现在我的问题是为什么std::swap不使用这种技术实现所以用户代码只需要调用std::swap

所以像这样(noexcept为了简洁而忽略和限制):

0 投票
0 回答
83 浏览

c++ - 为什么我们可以自定义ctors & dtors 但不能自定义访问器?

(这不是关于重载运算符的问题。一般来说。)

我们知道使用 setter 和 getter 方法有很多很好的理由。

那么,我觉得奇怪的是,这些不是成员访问的自定义点,即如果类 A 有一个数据成员 x,那么在左值上下文中使用 x 将不仅仅是使用 x,而是调用一些方法(比如A::get_x_lvalue(),别管语法)默认为

并且可以实现为覆盖,并且类似地,当在纯右值常量中使用 x 时,将调用可覆盖

...类似于,比如说,你如何在 Javascript 中做到这一点

我的问题是:

  • 从历史上看,为什么没有将它与可定制的复制构造函数、赋值运算符和析构函数一起添加到语言中?
  • 有没有正式提出过这样的事情?如果是这样,它的状态是什么或为什么被拒绝?
  • 除了: 1. 编译速度较慢和 2. 不能“相信” my_a.x 中的时间段只是普通访问之外,这种方案是否有重大损害?
0 投票
2 回答
206 浏览

c++ - 为什么`std::hash`不是通过重载作为`std::begin`的自定义点?

正如标题所说,std::beginstd::endstd::swap等是众所周知的std“定制点”(旨在由 ADL 找到的功能)。但是,std::hash我认为,唯一可由用户自定义的 std 行为暗示 (A) 打开std命名空间 (B) 创建部分专业化。

为什么没有std::hash像其他的那样通过重载函数而不是部分特化类来设计定制点?

0 投票
1 回答
68 浏览

c++ - 类模板名称中的隐藏朋友与内联命名空间中的另一个符号冲突

我想为我的类型提供一个隐藏的朋友,同时在内联命名空间中还有另一个同名的对象。一切都适用于普通类型。

但是如果我有一个模板,当我实例化模板时编译器会出错

这是代码:

较小的例子在这里

顺便说一句,我知道其他技术,例如tag_invoke但在这里我无法控制名称和库

0 投票
2 回答
342 浏览

c++ - 为什么在定义自定义点对象时需要删除函数?

从 libstdc++<concepts>头文件:

从 MS-STL<concepts>标头:

我从来没有遇到过= delete;你想禁止调用复制/移动分配/ctor的上下文。

我很好奇这是否有必要,所以我= delete;从库中注释掉了这样的部分:

查看以下测试用例是否编译。

它不仅可以编译,而且通过调用 user defined swapfor似乎表现良好struct dummy。所以我想知道,

  1. template<typename _Tp> void swap(_Tp&, _Tp&) = delete;在这种情况下究竟做了什么?
  2. 在什么情况下没有 template<typename _Tp> void swap(_Tp&, _Tp&) = delete;?
0 投票
1 回答
146 浏览

c++ - std 类型别名的自定义点

假设我正在lib命名空间中编写一些通用算法,该算法调用自定义点my_func

my_func 第一次尝试是为想要专门针对他的类型的用户使用 ADL my_func,这是std类型的别名。当然在他的命名空间中定义它是行不通的,因为 ADL 不适用于别名。std标准不允许在命名空间中定义它。剩下的唯一选项似乎在算法的命名空间中定义lib。但是,如果最终用户在包含自定义标头之前包含算法标头,这也不起作用。

https://godbolt.org/z/bfdP8s

第二次尝试是使用 niebloids my_func,这与 ADL 有相同的问题。

第三次尝试是 using tag_invoke,它应该与 ADL 有相同的问题,即

  • 在用户命名空间中自定义不起作用,因为我的类型是要std键入的别名
  • std不允许自定义
  • 命名空间中的自定义lib取决于标题包含的顺序 第一点似乎是正确的,但最后一点不是。这似乎有效

https://godbolt.org/z/hsKbKE

为什么这与第一个(原始 ADL)没有相同的问题?

第四次尝试是使用模板专业化,这似乎按预期正常工作

https://godbolt.org/z/r71x6c


编写通用算法和自定义点并允许客户端自定义 std 类型的别名的最佳方法是什么?

0 投票
2 回答
78 浏览

haskell - 如何优雅地处理算法的定制点以及对其参数的约束?

作为示例,让我们采用以下算法来计算两个序列的最长公共子序列,从Rosetta Code复制:

lcs隐含地假设两个参数都是 type Eq a => [a];实际上,如果我尝试明确给出签名lcs :: [a] -> [a] -> [a],则会在 where 行发生错误x == y,而签名lcs :: Eq a => [a] -> [a] -> [a]有效。

现在假设我有两个列表l1and l2,两者都是 type [(a,b)],并且我想要它们之间的 LCS,但是在==定义中使用运算符的方式lcs仅在snd每个元素的 s 之间(显然b需要属于Eqtypeclass) .

我不仅可以提供lcs这两个列表,还可以提供相等运算符,在上面的具体示例中是(==) `on` snd. 的签名lcs将是(a -> a -> Bool) -> [a] -> [a] -> [a]

然而,这将迫使用户提供相等运算符,即使是在人们想要使用 plain 的琐碎情况下,并且将参数(==)包装在 a 中也无济于事。(a -> a)Maybe

换句话说,我觉得在一般情况下,参数 via 的约束Eq a =>是可以的,但在其他情况下,可能想要传递一个自定义相等运算符来删除该约束,这使我成为函数重载的事情。

我该怎么办?

0 投票
1 回答
147 浏览

c++ - 自定义 BGL 图与拓扑排序一起工作需要什么?

我已经创建了一个自定义 BGL 图模型,就像在这个答案中一样:What is needed to use BGL algorithms on existing data structure ( edges and vertices as vector<Object *>)? .

它采用了一个自定义数据结构,用于一些 Boost.Graph 算法。

链接的答案足以让深度优先搜索工作(Coliru),但我在使用时遇到了问题boost::topological_sort

给予:科利鲁

“胶水”层必须满足哪些额外要求才能使用boost::topological_sort?在内部,拓扑排序使用depth_first_search,但似乎它可能需要顶点索引图。

0 投票
0 回答
45 浏览

c++ - 当其中一个函数实际上是函数对象时,修复或替代 ADL

在下面的代码中,命名空间中的独立组件S具有自己的定义BigSmall类型,以及将其拆分为 s 集合的split函数。BigSmall

S还提供了另一个函数 ,work它利用split, 并且旨在由其S自身以及其他依赖组件使用, 例如命名空间中的组件,D假定它们提供自己的定义BigSmall以及它们自己的split定义将通过 ADL 识别。¹

好吧,实际上S::split是一个函数对象,而不是一个函数²,

所以 ADL 不起作用。

关于如何解决这些需求的任何建议?

从评论中可以看出,Niebloids 和/或tag_invoke代表了我的问题的答案。我真的很想更多地了解这些概念。

目前,我对 Niebloids 的理解(我正在阅读Eric Niebler 的这篇博客)是它们是函数对象(当它们在范围内时)阻止 ADL,因此“集中”所有指向不合格自由函数的函数调用与 niebloid 同名;然而,它们operator()依赖 ADL 将调用转发到适当的自由函数。因此,看起来我的示例代码S::split中作为函数对象和D::split作为自由函数之间的对比无法由 niebloids 解决,除非我创建S::split了一个自由函数(在这种情况下,ADL 在我的简单场景中就足够了)。


¹ 最初是在andwork中定义的,上面的代码是我尝试的重构,在此期间我遇到了所描述的问题。SD

² 这样做的原因是,S::split它在多个上下文中使用S,它有一些重载operator(),最重要的是,它经常作为对象传递,非常方便。