c ++ 11绑定和应用? [英] c++11 bind and apply?

查看:173
本文介绍了c ++ 11绑定和应用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

std :: bind 有时被称为部分应用程序。

std::bind is sometimes described as "partial application". Any reasons why when all parameters of a function are bound, the function itself isn't applied?

例如,以下代码不打印任何内容。

For example, the following code prints nothing.

#include <functional>
#include <iostream>
using namespace std;
using namespace std::placeholders;

void f(int a,string b) {cout << a << b << endl;};
int main() {
  bind(bind(f,1,_1),"Hi!");
  return 0; 
}

有一种方法来写一个绑定变量,参数是固定的吗?

Is there a way to write a bind variant that can apply the function when all parameters are fixed?

- 更新 -

c> std :: bind 不是完全部分应用程序。所以,在问题的第二部分,我如何写一些像std :: bind但部分应用程序。
我知道 bind(bind(f,1,_1),Hi!)()将调用最后的0-ary函数并返回结果值(在示例中打印 1Hi )。是否可以在bind的终端情况下执行模板编程来调用函数调用operator()?

I understand from the responses now that std::bind is not exactly partial application. So, on the second part of the question, how can I write something like std::bind but does partial application. I know bind(bind(f,1,_1),"Hi!")() will call the final 0-ary function and return the result value (printing 1Hi in the example). Is it possible to do template programming to call the function call operator () in the terminal case of bind?

换句话说,可以写一个函数 bind1

In other words, is it possible to write a function bind1:

template< class R, class F, class... Args >
bind1( F f, Args... args )

c $ c> std :: is_placeholder< T> :: value == 0 为 args
bind1()可以,除了 std :: bind()

, such that when std::is_placeholder<T>::value == 0 for each member of args, bind1() can, in addition to what std::bind() does, call the operator()?

推荐答案

没有参数的函数只是Haskell中的一个值。你不叫它,你只是用它。因为没有副作用,所以没有可观察到的差异。

A function with no arguments is just a value in Haskell. You don't call it, you just use it. Since there are no side effects, there is no observable difference.

在OCaml中只有没有参数少的函数,要得到类似的东西,你需要添加一个虚拟单位参数。

In OCaml there are simply no parameter-less functions, to get something like that you need to add a dummy unit argument.

在C ++中不是这样。 C ++与Haskell和OCaml不同,在 f f()之间保持明显的区别。 bind 给你前者,因为你总是可以通过添加()将它变成后者。你可以为 bind 编写自己的包装,这很容易。

Not so in C++. C++, unlike Haskell and OCaml, maintains clear difference between f and f(). bind gives you the former because you can always turn it into the latter by adding (). You can write your own wrapper for bind that does just that quite easily. Going the other way around would be a tad more difficult.

这是一个可能的实现这样的包装:

Here's a possible implementation of such wrapper:

#include <functional>
#include <utility>
#include <iostream>

template <typename T>
struct is_noargs_callable {
  private:
    typedef char(&yes)[1];
    typedef char(&no)[2];

    template<typename U> 
      static yes test(decltype((std::declval<U>())())*);

    template<typename> 
      static no test(...);

  public:
    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

template <typename T>
struct is_noargs_callable<T()> {
  static const bool value = true;
};

template <typename T>
struct is_noargs_callable<T(...)> {
  static const bool value = true;
};

template <typename T>
auto call_me_if_you_can(T t) -> typename std::enable_if<is_noargs_callable<T>::value, decltype(t())>::type
{
  return t();
}

template <typename T>
auto call_me_if_you_can(T t) -> typename std::enable_if<!is_noargs_callable<T>::value, T>::type
{
  return t; 
}

template <typename... Args>
auto apply(Args&&... args) -> decltype(call_me_if_you_can(std::bind(args...))) {
  return call_me_if_you_can(std::bind(args...));
}

// testing

void foo(int a, int b, int c) { std::cout << "foo(" << a << "," << b << "," << c << ")";  }

int main ()
{
  using namespace std::placeholders;
  std::cout << "zero : " ; apply(foo, _1, _2, _3); std::cout << " : " ; apply(foo, _1, _2, _3)(1,2,3); std::cout << std::endl;
  std::cout << "one  : " ; apply(foo, 1, _1, _2); std::cout << " : " ; apply(foo, 1, _1, _2)(2,3); std::cout << std::endl;
  std::cout << "two  : " ; apply(foo, 1, 2, _1); std::cout << " : " ; apply(foo, 1, 2, _1)(3); std::cout << std::endl;
  std::cout << "three: " ; apply(foo, 1, 2, 3);  std::cout << " : "; /* nothing to test here */ std::cout << std::endl;
}

但是,消除 f f()只是在这一个地方没有IMHO有助于C ++编程的整体一致性。如果你不喜欢的区别,杀了它无处不在(或只是使用你一个Haskell伟大的好)。

However, killing the difference between f and f() just in this one place does not IMHO contribute to the overall consistency of C++ programming. If you don't like the distinction, kill it everywhere (or just use you a Haskell for great good).

这篇关于c ++ 11绑定和应用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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