локальная переменная как аргумент шаблона нетипичного типа - PullRequest
2 голосов
/ 29 июня 2011

Я хочу сделать что-то вроде следующего:

Example(&Class::MemberFunction, this));

//...

template<class T_CLASS>
inline static void Example(void (T_CLASS::*MemberFunctionPointer)(), T_CLASS* InstancePointer)
{
  SomeClass<T_CLASS>::Bind<MemberFunctionPointer>(InstancePointer);
}

Но я получаю ошибку: * параметр шаблона 'T_MEMBER_FUNCTION': 'MemberFunctionPointer': локальная переменная не может использоваться в качестве аргумента не-типа*

Какие-либо решения для этой проблемы?Я хочу предоставить более простой способ вызова «Bind»

Спасибо, Mirco

// edit:

Я хочу, чтобы MemberFunctionPointer был нетипичным параметром шаблона, потому что в«Привязать» мне снова нужно в качестве аргумента шаблона.Как вы написали в своих ответах, в моем случае MemberFunctionPointer является переменной, и ее значение неизвестно во время компиляции.Но MemberFunctionPointer всегда указывает на одну и ту же функцию.Есть ли способ, например, сделать его постоянным, чтобы компилятор знал это во время компиляции?

Ответы [ 4 ]

4 голосов
/ 29 июня 2011

Существуют два типа параметров шаблона: типы и константные выражения во время компиляции .Содержимое параметра функции не является определяемым во время компиляции значением.И поэтому компилятор не может создать экземпляр шаблона на его основе.

Помните: шаблон имеет тип .И типы должны быть определены во время компиляции.

Вы, вероятно, должны передать указатель на член в качестве аргумента функции Bind.

1 голос
/ 29 июня 2011

Параметры шаблона должны быть известны во время компиляции. Содержимое переменной-указателя, являющейся параметром функции, зависит от того, как эта функция вызывается. Это не известно во время компиляции!

Если вы уже знаете этот указатель во время компиляции, вы можете превратить параметр времени выполнения указателя функции в параметр шаблона:

template<class T_CLASS, void(T_CLASS::*MemFunPtr)()>
void Example(T_CLASS* InstancePointer) {...}

Здесь MemFunPtr - это параметр шаблона, который известен во время компиляции и поэтому может быть повторно использован как параметр шаблона для другой функции или шаблона класса ...

1 голос
/ 29 июня 2011

Я не совсем уверен, чего вы пытаетесь достичь?

Если MemberFunctionPointer является переменной, значение которой неизвестно во время компиляции и, например, может зависеть от некоторого поведения пользователя - тогда его нельзя использовать в качестве аргумента шаблона.

Если, с другой стороны, MemberFunctionPointer действительно может быть выведено во время компиляции, вы должны передать его в качестве аргумента шаблона, а не параметра функции. Рассмотрим следующий пример:

(используйте Bind и call в первом случае; во втором случае используйте StaticBind и callStatic)

#include <stdio.h>

class X {
  public:
    int x;
    void foo() {printf("foo\n");}
    void bar() {printf("bar\n");}
};

template <typename T>
class SomeClass {
  public:
    static void Bind(void (T::*MemberFunctionPointer)(), T *obj) {
      (obj->*MemberFunctionPointer)();
    }
    template <void (T::*MemberFunctionPointer)()>
    static void StaticBind(T *obj) {
      (obj->*MemberFunctionPointer)();
    }
};

template <class C>
static inline void call(void (C::*MemberFunctionPointer)(), C *obj) {
  SomeClass<C>::Bind(MemberFunctionPointer,obj);
}

template <class C, void (C::*MemberFunctionPointer)()>
static inline void callStatic(C *obj) {
  SomeClass<C>::template StaticBind<MemberFunctionPointer>(obj);
}

int main() {
  X obj;
  call<X>(&X::foo,&obj);
  callStatic<X,&X::bar>(&obj);
  return 0;
}
0 голосов
/ 29 июня 2011

MemberFunctionPointer - это переменная не типа (или константа времени компиляции) , поэтому ее нельзя использовать, вам нужна настоящая сигнатура этой функции, что-то вроде этого может быть лучше ..

template<typename T_FUNC_PTR, class T_CLASS>
inline static void Example(T_FUNC_PTR fPtr, T_CLASS* InstancePointer)
{
  SomeClass<T_CLASS>::Bind<T_FUNC_PTR>(fPtr, InstancePointer);
}

т.е. позволить компилятору определить тип указателя функции (ПРИМЕЧАНИЕ: вам также придется распространять указатель на функцию), чтобы вызвать

Example(&foo::bar, foo_inst);

Это не проверенои от макушки головы, так что синтаксис может быть немного неправильным ...

РЕДАКТИРОВАТЬ: вот более простой пример, чтобы продемонстрировать концепцию:

#include <iostream>
struct foo
{
  void bar() { std::cout << "foo::bar()" << std::endl; }
};

template<typename T_FUNC_PTR, typename T_CLASS>
void exec(T_FUNC_PTR ptr, T_CLASS& inst)
{
  (inst.*ptr)();
}

int main(void)
{
  foo inst;
  exec(&foo::bar, inst);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...