C++17 中如何防止函数参数从值类型转换为引用类型?

zig*_*tar 12 c++ c++17

使用 C++17,我有一个方法,该function方法采用带有必须是引用的参数的 a 。现在,当我传递采用非引用参数的 lambda 时,我不会收到编译错误。我希望这种情况不能编译。

我怎样才能实现这个目标?另外,哪个隐式转换会启动并导致非预期的代码编译?

#include <iostream>
#include <functional>

using namespace std;

void
takesRefLambda (function < void (string & t) > f)
{
  string test = "nope";
  f (test);
  cout << test << endl;
}

int
main ()
{
  //this shall fail at compile time, as parameter `q` is not a reference
  takesRefLambda ([&](string q)
          {
              q = "yep1";
          });

  //this shall compile
  takesRefLambda ([&](string & q)
          {
              q = "yep2";
          });

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Pas*_* By 15

std::function被设计为最大程度地灵活,根据需要转换任何参数。毕竟,这通常就是您想要的类型擦除效果。

转换std::function执行非常简单。鉴于您的签名void(std::string&)std::function::operator()或多或少

void operator()(std::string& s)
{
    callable(s);
}
Run Code Online (Sandbox Code Playgroud)

callable如果接受一个 ,这显然是有效的std::string

如果您必须有精确的函数签名,请对其进行测试

template<typename C>
void test(void (C::*) (std::string&));

template<typename C>
void test(void (C::*) (std::string&) const);

template<typename F>
auto takesRefLambda(F&& f)
    -> decltype(test<std::decay_t<F>>(&std::decay_t<F>::operator()))
{
    // use f
}
Run Code Online (Sandbox Code Playgroud)