С ++ Вывод параметров шаблона класса «указатель не на тип»

Рассмотрим класс шаблона как:

template<typename ReturnType, ReturnType Fn()>
class Proxy
{
    void run()
    {
        ReturnType ret = Fn();
        // ... do something ...
    }
};

// and a functions
int fn1() { return 5; }
float fn2() { return 5; }

Это может быть реализовано с помощью:

Proxy<int, &fn1> p1;

Но явное объявление типа возвращаемого значения кажется ненужным. То, что я пытаюсь достичь, это что-то вроде:

 someProxyInstantation<&fn1> p1;
 someProxyInstantation<&fn2> p2;

К сожалению, я не ожидаю c ++, и это похоже на скрытый угол языка (по крайней мере, для меня).

Если бы я мог просто получить от указателя на функцию до ее типа - что-то вроде: std :: tr1 :: result_of <& fn> :: type // Ошибка 1 ошибка C2923: 'std :: tr1 :: result_of': 'fn1 'не является допустимым аргументом типа шаблона для параметра' _Fty '

ошибка имеет смысл, поскольку параметр вообще не является "типом"

C ++ 0x имеет тип decl (& fn1), но это через много лет.

Любой способ сделать это в C ++ 03 (+ tr1)?

Ограничения: - Я не хочу передавать функтор, f1 и f2 должны оставаться глобальными функциями, которые имеют возвращаемое значение (не может переместить его в параметр).)

15.12.2008 15:39:10
1 ОТВЕТ
РЕШЕНИЕ

Это невозможно в C ++ 03. Если вы хотите передать указатель на функцию как не типовой параметр, компилятор должен знать тип параметра. Таким образом, вы должны предоставить недостающие части (в данном случае, тип возврата). Вы можете дать прокси указатель функции в качестве значения во время выполнения и указать его тип в качестве единственного аргумента. Тогда вы могли бы написать функцию генератора для вас, которая выполняет эту работу:

template<typename T>
Proxy<T> make_proxy(T t) { return Proxy<T>(t); }

К сожалению, в текущем C ++ вам все еще нужно дать ему тип для присваивания автоматической переменной:

Proxy<int(*)()> p = make_proxy(&fn1);

Вы не можете использовать auto p = make_proxy(&fn1);еще. Обратите внимание, что если вы хотите использовать тип функции с левой стороны, вам нужно изменить функцию генератора, чтобы обеспечить не тип указателя функции:

template<typename T>
Proxy<typename boost::remove_pointer<T>::type> make_proxy(T t) { 
    return Proxy<typename boost::remove_pointer<T>::type>(t); 
}

Теперь вы можете сделать

Proxy<int()> p = make_proxy(&fn1);

используя прокси, теперь вы можете просто сделать

doSomething(make_proxy(&fn1));

И если doSomething является шаблонным или иным образом полиморфным, вам не потребуется знать точный тип функции.

6
15.12.2008 15:58:59
До c ++ 0x это придется делать.
Hrvoje Prgeša 16.12.2008 00:06:59