像 `declval` 的概念

Something like `declval` for concepts

当您使用模板和 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.

即将发布的标准中是否有允许这样做的机制?我会发现这非常有用。


编辑:前段时间我问 是否可以用 boost::hana 来完成。


编辑:为什么这有用?例如,如果你想写一个由两个函数组成的函数

template <typename F, typename G>
auto compose(F f, G g) {
  return [f, g](Incrementable auto x) { return f(g(x)); };
}

我想在尝试组合两个无法组合的函数时出现错误。在不限制类型 FG 的情况下,仅当我尝试调用组合函数时才会出错。

没有这样的机制。

这似乎也不是 implementable/useful,因为有无限数量的 Incrementable 类型,并且 F 可以拒绝使用任意复杂的元程序选择的子集。因此,即使您可以神奇地合成一些独特的类型,您仍然无法保证 F 对所有 Incrementable 类型都有效。

Is there a something similar for concepts? i.e. a function which would create and imaginary type for a concept.

这个术语是原型。提出原型将是一个非常有价值的特性,并且对于进行定义检查之类的事情至关重要。来自T.C.的回答:

Thus, even if you could magically synthesize some unique type, you still have no guarantee that F operates on all Incrementable types.

这样做的方法是合成一个原型,该原型尽可能满足概念的标准。正如他所说,C++20 中没有原型生成,考虑到当前的概念化身,这似乎是不可能的。


想出正确的原型非常困难。例如,对于

template <typename T>
concept Incrementable = requires(T t){
   { ++t } -> T;                       
};

写的很诱人:

struct Incrementable_archetype {
    Incrementable_archetype operator++();
};

但这不是 "as minimal as possible" - 这种类型是默认可构造和可复制的(不是 Incrementable 强加的要求),并且它的 operator++ returns 恰好 T,这也不是要求。所以一个真正的硬核原型应该是这样的:

struct X {
    X() = delete;
    X(X const&) = delete;
    X& operator=(X const&) = delete;

    template <typename T> operator,(T&&) = delete;

    struct Y {
        operator X() &&;
    };
    Y operator++();
};

如果您的函数适用于 X,那么它可能适用于所有 Incrementable 类型。如果您的函数不适用于 X,那么您可能需要更改实现以使其适用或更改约束以允许更多功能。

有关更多信息,请查看 Boost Concept Check Library,它很旧,但至少阅读文档非常有趣。