Передача функции в качестве аргумента шаблона класса - PullRequest
5 голосов
/ 17 апреля 2011

Не зная типа функции, я объявляю ее указатель с помощью техники ниже и инициализирую указатель функции.

template<typename T>
struct Declare { typedef T Type; }; // for declaring any func ptr

void fun () {}

int main ()
{
  Declare<fun>::Type pf = &fun;  // can't use C++0x 'auto'
}

Однако, она выдает ошибку компиляции как error: expected a type, got ‘fun’.Хотя тип любого метода известен во время компиляции. Неправильно ли передавать функцию в класс template, как указано выше?

[Примечание: замена fun на void (*)() работает нормально.Но это не то, что нужно.]

Ответы [ 2 ]

5 голосов
/ 17 апреля 2011

Неправильно ли передавать функцию в шаблон класса, как указано выше?

В общем, да, вы смешиваете типовые и нетиповые параметры.
funявляется аргументом не тип , это адрес функции, например, произвольное число 0x12345678.
typename T является параметром тип .Вы можете передавать только такие типы, как int, MyClass, double (*)(std::string), void (MyClass::*)().
Вам просто придется смириться с тем фактом, что вам нужна поддержка компилятора для этого материала или какой-то действительно уродливыйхитрость, чтобы вывести тип.
Если вы за хитрость, есть Boost.Typeof для не-C ++ 0x кодера, как вы.Он также обеспечивает замену auto с BOOST_AUTO, но это только короткий путь для записи BOOST_TYPEOF:

int hello(){ return 42; }
BOOST_AUTO(var1,hello()); // type of var1 == int
BOOST_TYPEOF(hello()) var2 = hello(); // same

Проблема?Вы должны помочь этому для каждого пользовательского типа, который у вас есть.См. этот пример Ideone .


Теперь, в большинстве случаев, я не думаю, что вам нужен Boost.Typeof.Зачем?Потому что, если вы используете функцию, вам, конечно, нужно знать сигнатуру, как бы вы в противном случае передавали правильные аргументы?Или правильно использовать тип возвращаемого значения?
В любом случае, использование шаблонов в любом случае.Если вы объявляете указатель на функцию типа auto fptr = &func, то вы знаете, что существует func, то есть вы знаете его сигнатуру и тип.Поскольку, когда вы не знаете, что func существует, вам все равно нужно передать его вам, желательно в шаблоне:

template<class FPtr>
void myfunc(FPtr otherfunc){
  // use otherfunc
}

И с шаблоном вы снова узнаете об этом типе функций.

3 голосов
/ 17 апреля 2011

Неправильно ли передавать функцию в шаблон класса, как указано выше?

Да. Потому что вы, другими словами, хотите, чтобы компилятор выводил параметр type для шаблона класса, что просто невозможно в C ++. Напомним, что fun сам по себе не является типом , его значением типа void (*)(). Но ваш шаблон класса ожидает тип, а не значение. Вот почему это не сработает.

Вывод типа возможен только с функциями, то есть даже с конструктором класса. Так что если вы пишете шаблонный конструктор, а затем вы можете написать это:

Declare obj(&fun); 

Здесь тип функции известен, пока вы находитесь в конструкторе, как только вы существуете из него, вы теряете информацию. Итак, что вам, вероятно, нужно: определить класс, скажем, AbstractFunctor (возможно, шаблон класса) и, исходя из него, определить другой класс, скажем template<Fun fun> struct Functor. Затем вы можете создать экземпляр Functor, который может запомнить тип функции навсегда, и сохранить экземпляр в AbstractFunctor* как данные-члены Declare.

Но я думаю, что даже в этом случае тип нельзя использовать как Declare::Type или Declare::AbstractFunctor::Type, просто потому, что тип * хранится в экземпляре класса ; только экземпляр знает тип . Таким образом, получение типа с использованием синтаксиса типа A::Type не может быть и речи. И вы не можете получить тип с использованием синтаксиса instance.Type либо. Все, что вы можете сделать, это: вызвать функцию, используя instance , как функтор.


EDIT:

Если вам разрешено использовать другие функции C ++ 0x (кроме auto), тогда проблема имеет тривиальное решение:

Declare<decltype(&fun)>::Type pf = &fun;  
pf(); //call the function

Демо: http://ideone.com/

Но тогда вам даже не нужно даже Declare, поскольку вы можете сделать это вместо этого:

decltype(&fun) pf = &fun; 
pf(); //call the function   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...