Я пишу функтор F, который принимает функцию типа void (* func) (T) и аргумент func arg.
template<typename T>
void F(void (*func)(T), WhatTypeHere? arg)
{
func(arg);
}
Тогда функтор F вызывает func с помощью arg. Я хотел бы, чтобы F не копировал arg, просто чтобы передать его как ссылку. Но тогда я не могу просто написать «void F (void (* func) (T), T &)», потому что T может быть ссылкой. Поэтому я пытаюсь написать характеристику, которая позволяет получить правильный тип ссылки T:
T -> T&
T& -> T&
const T -> const T&
const T& -> const T&
Я придумываю что-то вроде этого:
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);
}
Что не работает, например, для
void a(int x) { std::cout << x << std::endl; }
F(&a, 7);
Ошибка выдачи:
неверная инициализация неконстантной ссылки типа 'int &' из временного типа 'int' при передаче аргумента 2 типа 'void F (void (*) (T), typename type_op :: valid_ref_type) [with T = int]'
Как заставить эту черту работать?