c ++ вывод параметров шаблона класса «указатель не на тип» - PullRequest
4 голосов
/ 15 декабря 2008

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

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 должны оставаться глобальными функциями, которые имеют возвращаемое значение (не может переместить его в параметр).)

1 Ответ

6 голосов
/ 15 декабря 2008

Это невозможно в 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 является шаблонным или иным образом полиморфным, вам не потребуется знать точный тип функции.

...