简体   繁体   English

如何用C ++模板模拟高阶函数?

[英]How to emulate higher order function with C++ templates?

Here's a the template lessThan which works as a function. 这是一个模板lessThan ,可以用作功能。

template<int n>
struct Box
{
};

template<typename T>
struct Unbox_;

template<int n>
struct Unbox_<Box<n>>
{
    static constexpr int value = n;
};

template<typename T>
constexpr int unbox = Unbox_<T>::value;

template<typename T, typename U>
struct LessThan_
{
    static constexpr bool value = unbox<T> < unbox<U>;
};

template<typename T, typename U>
constexpr bool lessThan = LessThan_<T, U>::value;

#include <iostream>

int main()
{
    std::cout << lessThan<Box<1>, Box<2>> << '\n';
    std::cout << lessThan<Box<3>, Box<2>> << '\n';
}

I now want to do something like this 我现在想做这样的事情

lessThan<Box<1>><Box<2>> == true

which is of course not valid C++. 这当然不是有效的C ++。 Why do I need this? 我为什么需要这个? Consider below. 考虑下面。

template<typename T>
struct LessThanOne_
{
    static constexpr bool value = unbox<T> < 1;
};

template<typename T>
constexpr bool lessThanOne = LessThanOne_<T>::value;

In some places where I need to pass a template with one parameter, instead of passing lessThanOne , I want to pass something like lessThan<Box<1>> , so that I don't need to hardcode all cases. 在某些地方,我需要传递一个参数的模板,而不是传递lessThanOne ,而不是传递lessThan<Box<1>> ,这样就不需要对所有情况进行硬编码。 Is there any workaround? 有什么解决方法吗?

You are looking for the concept calked currying. 您正在寻找“ ked缩”的概念。 Look it up. 查一下 Here's a quickly thrown together sample implementation: 这是一个快速汇总的示例实现:

template<template<class,class> class fn>
struct curry
{
  template <class A>
  struct apply1
    {
      template <class B>
      using apply = fn<A,B>;
    };
 template<class A>
 using apply = apply1<A>;
};

// That's it. Below is a test rig.

template <class>
struct test1 {};

template <template<class>class>
struct test2{};

// a meta function to test 
template <class, class>
struct myfn {};

// same function, curried 
using myfngood = curry<myfn>;

// fully applied myfngood is a type
test1 <myfngood::apply<int>::apply<char*>> t1;

// partially applied myfngood is a template
test2 <myfngood::apply<int>::apply> t2;

As RedX's comment: 正如RedX的评论:

template<typename RHS>
struct LessThanN {
    template <typename LHS>
    struct inner { 
        static constexpr bool value = unbox<LHS> < unbox<RHS>;
    };
};

and use it like: 并像这样使用它:

template <typename LHS>
using LessThanOne = LessThanN<Box<1>>::inner<LHS>;

int main() {
    auto x = LessThanN<Box<2>>::inner<Box<1>> {};
    cout << "1<2 " << boolalpha << x.value << '\n';
    cout << "3<2 " << boolalpha << LessThanN<Box<2>>::inner<Box<3>>::value << '\n';
    cout << "0<1 " << boolalpha << LessThanOne<Box<0>>::value << '\n';
}

Having said that, your original motivational example seems to be perfectly workable if you correct the syntax error, although it doesn't deal with partial application: 话虽如此,但是如果您纠正语法错误,那么您的原始动机示例似乎是完全可行的,尽管它不能处理部分应用程序:

template<typename T, typename U>
struct LessThan_ {
    static constexpr bool value = unbox<T> < unbox<U>;
};

template<typename T, typename U>
constexpr bool lessThan = LessThan_<T, U>::value;

static_assert(lessThan<Box<1>, Box<2>> == true, "check");
// NOT lessThan<Box<1>><Box<2>> == true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM