C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 如何绑定传递未指定的调用包装器的成员函数模板大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我尝试使用VC11和g 4.7.2编译以下示例:
#include <functional>

class X {
public:
  template <typename T>
  explicit X(T t)
  {
    std::bind(&X::invoke<T>,this,t)();
  }
private:
  template <typename T>
  void invoke(T t)
  {
    t();
  }
};

class Y {
  public:
    void foo() {
      //...
    }
};


int main() {
  Y y;
  X x(std::bind(&Y::foo,&y));
  return 0;
}

但它完成了错误.我不确定粘贴整个编译器输出是否合理,但一般情况下

vc11说:

和g:

有没有办法解决这个问题.保存主要思想对于我来说非常重要 – 可以用任何可调用对象(函数对象,函数指针或std :: bind()函数返回的调用包装器)实例化的类.

如果有人帮忙,我将不胜感激.

附:如果我创建一个X实例,传递函数对象或函数指针,它编译.

解决方法

问题的根本原因似乎是由std :: bind执行其参数的内部复制,特别是对t的引用.

您可能希望以这种方式解决它:

template <typename T>
  explicit X(T t)
  {
      std::bind(&X::invoke<T>,std::placeholders::_1)(t);
      //                             ^^^^^^^^^^^^^^^^^^^^^  ^
  }

这也可以,但是你不会允许绑定的结果比参数t更长(否则,你将传递一个悬空引用来调用< T>()):

template <typename T>
  explicit X(T t)
  {
      std::bind(&X::invoke<T>,cref(t))();
      //                             ^^^^^^^
  }

更新:

上述解决方案是有助于实现您在示例中显示内容解决方法.但是,从评论中可以看出,您的用例可能大不相同(例如,传递绑定结果以供以后评估).

正如Maxim Yegorushkin在他的回答中正确指出的那样,概念上正确的解决方案在于使用诸如Boost的保护之类的结构.

如果您不想使用Boost,使用C 11的可变参数模板定义您自己的protect()函数非常容易:

// Imitates boost::protect,but with variadic templates and perfect forwarding
namespace detail
{
    template<typename F>
    struct protect
    {
    private:

        F _f;

    public:

        explicit protect(F f): _f(f)
        {
        }

        template<typename... Ts>
        auto operator () (Ts&&... args) -> 
            decltype(_f(std::forward<Ts>(args)...))
        {
            return _f(std::forward<Ts>(args)...);
        }
    };
}

template<typename F>
detail::protect<F> protect(F&& f)
{
    return detail::protect<F>(std::forward<F>(f));
}

最终,这是你在课堂上使用它的方式,正如Maxim建议的那样:

class X
{
public:
    template <typename T>
    explicit X(T t)
    {
        auto pt = protect(t);
        std::bind(&X::invoke<decltype(pt)>,pt)();
    }
private:
    template <typename T>
    void invoke(T t)
    {
        t();
    }
};

大佬总结

以上是大佬教程为你收集整理的c – 如何绑定传递未指定的调用包装器的成员函数模板全部内容,希望文章能够帮你解决c – 如何绑定传递未指定的调用包装器的成员函数模板所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: