Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get const or non-const reference type from trait

I am writing a functor F which takes function of type void (*func)(T) and func's argument arg.

template<typename T>
  void F(void (*func)(T), WhatTypeHere? arg)
{
  func(arg);
}

Then functor F calls func with arg. I would like F not to copy arg, just to pass it as reference. But then I cannot simply write "void F(void (*func)(T), T&)" because T could be a reference. So I am trying to write a trait, which allows to get proper reference type of T:

T -> T&
T& -> T&
const T -> const T&
const T& -> const T&

I come up with something like this:

template<typename T>
 struct type_op
{
 typedef T& valid_ref_type;
};

template<typename T>
 struct type_op<T&>
{
 typedef typename type_op<T>::valid_ref_type valid_ref_type;
};

template<typename T>
 struct type_op<const T>
{
 typedef const T& valid_ref_type;
};

template<typename T>
 struct type_op<const T&>
{
 typedef const T& valid_ref_type;
};


template<typename T>
  void F(void (*func)(T), typename type_op<T>::valid_ref_type arg)
{
  func(arg);
}

Which doesn't work for example for

void a(int x) { std::cout << x << std::endl; }
F(&a, 7);

Giving error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘int’ in passing argument 2 of ‘void F(void (*)(T), typename type_op::valid_ref_type) [with T = int]’

How to get this trait to work?

like image 648
maciekp Avatar asked Apr 14 '26 00:04

maciekp


1 Answers

template<class T>
struct forwarding { typedef T const& type; };
template<class T>
struct forwarding<T&> { typedef T& type; };

template<typename T>
void F(void (*func)(T), typename forwarding<T>::type arg) {
  func(arg);
}

void a(int x) { std::cout << x << std::endl; }
int main() {
  F(&a, 7);
}

Your mapping was close, you actually want T mapped to T const& too:

T        -> T const&
T&       -> T&
T const& -> T const&

Note that functions having a parameter type of T const have a signature of T! The const is an implementation detail:

void f(int const);
typedef void F(int); // typedef of function type
F* p = &f; // no error! f's signature doesn't include const

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!