首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++11绑定和应用?

c++11绑定和应用?
EN

Stack Overflow用户
提问于 2014-01-21 02:14:15
回答 2查看 737关注 0票数 2

std::bind有时被描述为“部分应用程序”。当函数的所有参数都被绑定时,函数本身没有被应用的原因吗?

例如,下面的代码不输出任何内容。

代码语言:javascript
复制
#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; 
}

是否有一种方法可以在所有参数固定时应用该函数的绑定变量?

-更新

我从响应中了解到,std::bind并不完全是部分应用程序。因此,在问题的第二部分,我如何编写类似于std::bind但是部分应用程序的东西。我知道bind(bind(f,1,_1),"Hi!")()将调用最后的0进制函数并返回结果值(在示例中打印1Hi )。在绑定的终端情况下,是否可以执行模板编程来调用函数调用操作符()?

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

代码语言:javascript
复制
template< class R, class F, class... Args >
bind1( F f, Args... args )

,这样,当std::is_placeholder<T>::value == 0针对args的每个成员时,除了std::bind()的功能之外,bind1()还可以调用operator()?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-21 04:28:13

没有参数的函数只是Haskell中的一个值。你不叫它,你就用它。由于没有副作用,所以没有明显的差别。

在OCaml中,不存在没有参数的函数,要获得类似的内容,需要添加一个虚拟的单元参数。

但在C++中并非如此。C++与Haskell和OCaml不同,它在ff()之间保持着明显的区别。bind给出了前者,因为您总是可以通过添加()将其转换为后者。您可以为bind编写自己的包装器,这样做非常容易。往相反的方向走会有点困难。

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

代码语言:javascript
复制
#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;
}

然而,仅仅在这一点上消除ff()之间的差异并不能提高C++编程的整体一致性。如果你不喜欢这种区别,那就把它消灭在任何地方(或者干脆用你一只Haskell来做个大好事)。

票数 2
EN

Stack Overflow用户

发布于 2014-01-21 02:21:13

没有消息来源,只有我的意见。

之所以没有这样做,是因为没有理由去做。如果您知道该函数的所有输入,只需调用它。

如果您正在使用模板进行操作,从而导致这种情况,那么无论如何您都需要始终如一地编写所有代码。这里的特例只需要其他地方的特例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21247882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档