C ++概念:我可以定义一个本身就是模板的概念吗? [英] C++ Concepts: Can I define a concept that is itself a template?

查看:72
本文介绍了C ++概念:我可以定义一个本身就是模板的概念吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很抱歉,这个问题不太清楚。我不确定用它表达短语的最佳方法(随时可以编辑!)。我认为一个例子将是最清楚的:

Sorry if the question isn't too clear. I'm not sure the best way to phrase it (feel free to edit!). I think an example would be the most clear:

我正在尝试基于 Haskell定义。绑定运算符(> == )要求类型为 A <的 Monad / code>可以绑定到接受 A 并返回 Monad 类型的函数。 c $ c> B 。我可以使用 value_type typedef来定义 A ,但是如何定义 B 是我的概念?

I am attempting to define a Monad concept based off of the Haskell definition. The bind operator (>>=) requires that a Monad of type A can be bound to a function that takes an A and returns a Monad of type B. I can define A in terms of a value_type typedef but how do I define type B in my concept?

template <typename M>
concept bool Monad()
{
  return requires(M m, Function<_1, ValueType<M>> f) {
    // (>>=) :: m a -> (a -> m b) -> m b
    { m >>= f } -> M
  }
}

在上面的示例中,我要输入什么 _1 在Function<>概念中的位置?

In the above example, what do I put in place of the _1 in the Function<> concept?

这是否也充分限制了调用f的结果是任何类型的Monad?

Also does this sufficiently constrain the result of invoking f to be a Monad of any type?

推荐答案

我认为您可能能够做的最接近的事情是提供特定于 函数是 A-> Monad< B> 并验证其是否正确。为了防止无限递归,我们只需要验证 A-> M 的工作原理:

I think the closest you may be able to do is to provide a specific function that is A --> Monad<B> and verify that it does the right thing. In an effort to prevent infinite recursion, we can just verify that A --> M works:

template <class M>
concept bool Monad()
{
    return requires(M m) {
        { m >>= std::function<M(ValueType<M>)>{} } -> M;
    };
}

这只是一种情况,但我认为这是不可能的验证 A->的一般情况Monad< X> 可以工作,因为概念检查仍涉及特定的表达式,并且您只能创建具有特定类型的特定表达式。

This is only one specific case, but I don't believe it is possible to verify the general case that A --> Monad<X> works, since the concepts checks still involve specific expressions and you can only create specific expressions with specific types.

当然,我们可以提供多个这样的要求。具有重新绑定的元函数:

Of course, we can provide multiple such requirements. With a rebind metafunction:

template <class M, class X>
struct rebind;

template <class M, class X>
using rebind_t = typename rebind<M, X>::type;

template <template <class...> class Z, class R, class X>
struct rebind<Z<R>, X> {
    using type = Z<X>;
};

然后我们可以添加对返回各种类型的函数的要求,说它也适用于 int s:

We can then add requirements for functions returning various types, say that it also works for ints:

template <class M>
concept bool Monad()
{
    return requires(M m)
    {
        { m >>= std::function<M(ValueType<M>)>{} } -> M;
        { m >>= std::function<rebind_t<M,int>(ValueType<M>)>{} } -> rebind_t<M,int>;
    };
}

通过将其重构为自己的子概念可能会更容易:

which might get easier by refactoring that into its own sub-concept:

template <class M, class R>
concept bool MonadBind()
{
    return requires(M m) {
        { m >>= std::function<rebind_t<M,R>(ValueType<M>)>{} } -> rebind_t<M,R>;
    };
}

template <class M>
concept bool Monad()
{
    return requires(M m) {
        requires MonadBind<M, ValueType<M>>();
        requires MonadBind<M, int>();
    };
}

这篇关于C ++概念:我可以定义一个本身就是模板的概念吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆