微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 C++ 中使用可变参数函数编译错误

如何解决在 C++ 中使用可变参数函数编译错误

我有一段不能很好编译的代码。 我将可变参数函数和绑定函数一起使用。编译器错误信息显示

error: no match for call to ‘(std::_Bind<std::_Mem_fn<void (SimpleList::*)(int&&)>(std::_Place holder<1>,int)>) (SimpleList&)’ slistinitter(simpleList);

#include <iostream>
#include <functional>

template <typename T>
std::reference_wrapper<T> maybe_wrap(T& val) 
{ 
  std::cout << "this is lvalue\n";
  return std::ref(val); 
}

template<typename T>
T&& maybe_wrap(T&& val) 
{ 
  std::cout << "this is rvalue\n";
  return std::forward<T>(val); 
}

void print(){}

template<typename T,typename... Args>
void print(const T& t,Args&&... args)
{
  std::cout << t << std::endl;
  print(std::forward<Args>(args)...);
}

class SimpleList
{
public:
  template<typename... Args>
  void init(Args&&... args)
  {
    std::cout << __FUNCTION__ << std::endl;
    print(std::forward<Args>(args)...);
  }
};

template<typename SLIST>
class Collection
{
public:
  template<typename SLIStiniTTER>
  void initCollection(SLIStiniTTER slistinitter)
  {
    std::cout << __FUNCTION__ << std::endl;
    SLIST simpleList;
    slistinitter(simpleList);
  }
  template<typename... Args>
  void init(Args&&... args)
  {
    initCollection(std::bind(&SLIST::template init<Args...>,std::placeholders::_1,maybe_wrap(std::forward<Args>(args))...));
  }
};

class test
{
public:
  void work(const std::string& p1)
  {
    std::cout << p1 << std::endl;
  }
  test(){}
  test(const test&)
  {
    std::cout << "this is copy\n";
  }
  test(test&& t)
  {
    std::cout << "this is move\n";
  }
  friend std::ostream& operator<<(std::ostream& os,const test& t);
};

std::ostream& operator<<(std::ostream& os,const test& t)
{
  os << "cool";
  return os;
}

int main()
{
  using Sample = Collection<SimpleList>;
  Sample s;
  test t;
  int i = 2;
  s.init(2);

  return 0;
}

如果我使用 i 作为左值传递给 init 函数。它可以很好地编译。

解决方法

std::bind 生成的函子中的数据成员存储为 Lvalues

取自std::bind reference

成员对象 std::bind 的返回类型持有一个成员对象 输入从 std::forward(f) 构造的 std::decay::type,和一个 对象每个 args...,类型为 std::decay::type,类似 从 std::forward(arg_i) 构造。

您的代码可以简化为:

struct Foo {
    template<class T>
    void Bar(T&&) {}
};

int main() {
    Foo f;
    auto b = std::bind(&Foo::Bar<int>,std::placeholders::_1,2);
    b(f);
}

代码无法编译。传递的 2 存储为左值,但我们指定有界函数的签名为 Foo::Bar(int&&) -> 接受右值引用。左值不能绑定到右值。这就是问题所在。作为修复,我们可以在 int& - Bar 的模板参数列表中传递 &Foo::Bar<int&>

您的代码更改为 std::bind(&SLIST::template init<Args&...>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。