Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent function parameter conversion from value to reference type in C++17?

Tags:

c++

c++17

Using C++17, I have a method that takes a function with a parameter that must be a reference. Right now, I do not get a compilation error when I pass a lambda taking a non-reference parameter. I want this situation to not compile.

How can I achieve this? Also which implicit conversion kicks in and causes the not intended code to compile?

#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;
}
like image 705
ziggystar Avatar asked Feb 24 '26 14:02

ziggystar


1 Answers

std::function is designed to be maximally flexible, converting any arguments as necessary. This is usually what you want with type-erasure after all.

The conversions std::function performs are straightforward. Given your signature void(std::string&), std::function::operator() is more or less

void operator()(std::string& s)
{
    callable(s);
}

Which is obviously valid if callable accepts a std::string.

If you must have an exact function signature, test for it

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
}
like image 153
Passer By Avatar answered Feb 27 '26 04:02

Passer By