I am writing a functor F that takes a function like void (* func) (T) and argument func argument.
template<typename T>
void F(void (*func)(T), WhatTypeHere? arg)
{
func(arg);
}
Then the functor F calls func with arg. I would like F not to copy arg, just to pass it as a reference. But then I can’t just write "void F (void (* func) (T), T &)", because T can be a link. Therefore, I am trying to write a trait that allows you to get the correct reference type 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);
}
What does not work, for example, for
void a(int x) { std::cout << x << std::endl; }
F(&a, 7);
Error on receipt: invalid initialization of a non-constant reference of type 'int & from a temporary type' int in passing argument 2 of 'void F (void (*) (T), typename type_op :: valid_ref_type) [with T = int]
How to make this feature work?