像`declval`这样的概念

时间:2018-12-02 01:00:53

标签: c++ templates c++-concepts c++20

使用模板和decltype时,即使您没有时间,也经常需要某种类型的实例。在这种情况下,std::declval<T>()非常有用。这将创建一个T类型的虚构实例。

概念是否有类似之处?即可以为概念创建虚构类型的函数。

让我给你一个例子(有点作弊,但应该达到目的):

让我们定义一个概念Incrementable

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

现在,我想提出一个概念来测试对象是否具有可以接受operator()的运算符Incrementable。用我虚构的语法,我会这样写:

template <typename F, typename T = declval<Incrementable>>
concept OperatesOnIncrementable = requires(F f, T t){
   { f(t) } -> T;
} 

declval中的typename T = declval<Incrementable>会创建一个虚构的类型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)); };
}

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

2 个答案:

答案 0 :(得分:7)

没有这种机制。

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

答案 1 :(得分:4)

  

概念是否有类似之处?即可以为概念创建虚构类型的函数。

此术语是原型。提出原型将是非常有价值的功能,并且对于进行定义检查等操作至关重要。来自T.C.的答案:

  

因此,即使您可以神奇地合成某些唯一类型,也无法保证F对所有Incrementable类型都有效。

做到这一点的方法是合成一个尽可能最小地满足该概念标准的原型。正如他所说,C ++ 20中没有原型生成,并且鉴于当前的概念化,这似乎是不可能的。


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

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

很容易写:

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

但这并不是“尽可能的少”-这种类型是默认可构造和可复制的(不是Incrementable提出的要求),并且它的operator++返回的恰好是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,它虽然很旧,但是至少阅读文档非常有趣。