【发布时间】:2018-12-02 01:00:52
【问题描述】:
当您使用模板和decltype 时,您经常需要某种类型的实例,即使您没有任何时间。在这种情况下,std::declval<T>() 非常有用。这会创建一个T 类型的虚构实例。
在概念上有类似的东西吗?即为概念创建和想象类型的函数。
让我举个例子(有点做作,但应该达到目的):
让我们定义一个概念Incrementable
template <typename T>
concept Incrementable = requires(T t){
{ ++t } -> T;
};
现在我想有一个概念来测试一个对象是否具有可以接受Incrementable 的运算符operator()。在我想象的语法中,我会这样写:
template <typename F, typename T = declval<Incrementable>>
concept OperatesOnIncrementable = requires(F f, T t){
{ f(t) } -> T;
}
typename T = declval<Incrementable> 中的 declval 将创建一个虚构的类型 T,它并不是真正的具体类型,但从所有意图和目的来看,它的行为都类似于满足 Incrementable 的类型。
即将发布的标准中是否有机制允许这样做?我会发现这非常有用。
编辑:前段时间我问过similar question 是否可以用boost::hana 完成。
编辑:为什么这有用?例如,如果你想编写一个由两个函数组成的函数
template <typename F, typename G>
auto compose(F f, G g) {
return [f, g](Incrementable auto x) { return f(g(x)); };
}
当我尝试组合两个无法组合的函数时,我想得到一个错误。在不限制 F 和 G 类型的情况下,只有在尝试调用组合函数时才会出错。
【问题讨论】:
-
“我会发现这非常有用。”我不确定我是否明白为什么。就像,我可以理解你为什么要限制一个函数/类
f(t)是否产生T类型的值。我理解你为什么要将T限制为Incrementable。但我看不出在justF的基础上约束模板有什么用处。也就是说,有人会使用OperatesOnIncrementable<F>作为约束,而不提供T。那有什么好处? -
@NicolBolas 我已经编辑了我的答案,以举一个有用的例子。
-
为什么你的
compose函数需要约束传递给内部函数的类型?如果您正在编写函数,请编写它们;让g的性质决定作品的运作方式。 -
@NicolBolas 概念的一大优势是它们可以及早发现错误并为您提供有意义的错误消息。在我的示例中,如果您执行无效合成并将其传递给某个算法怎么办。你可能会从算法的深处得到一个可怕的错误。
-
你想要parametricity,但 C++ 没有。模板和概念不符合条件。如果您想要一种具有参数化的语言,请考虑 Haskell、OCaml 或 Scala。
标签: c++ templates c++-concepts c++20