Перегрузить указатель на перегруженную функцию - PullRequest
2 голосов
/ 08 октября 2011

Если я пытаюсь определить указатель на перегруженную функцию

void myprint(int );
void myprint(const char* );
void (*funpointer)(int) = myprint;

компилятор понимает, что funpointer должен указывать на версию myprint, которая соответствует его аргументам. Вместо этого я хочу, чтобы funpointer также был перегружен.
Я попытался просто добавить пару строк, как

void myprint(int );
void myprint(const char* );
void (*funpointer)(int);
void (*funpointer)(const char *);
void funpointer = myprint;

но затем компилятор жалуется на конфликтующие объявления для funpointer (очевидно).

Есть ли способ достичь того, что я ищу? Я хотел бы, чтобы указатель вел себя как перегруженная функция. Таким образом, я мог бы назвать его как funpointer(1) или funpointer("Hey."), и он работал бы как соответствующая версия myprint.

Ответы [ 5 ]

2 голосов
/ 08 октября 2011

Почему ты это делаешь? Указатели на функции предназначены для полиморфизма во время выполнения в зависимости от состояния приложения. Обычные старые перегрузки работают нормально, если единственная разница - это тип аргумента.

Если вы хотите иметь возможность, скажем, написать библиотеку, которая будет вызывать перегрузки, определенные позже, в коде клиента, сделайте что-то вроде следующего:

void foo(int x) { printf("int\n");}
void foo(const char* c){ printf("char*\n"); }

template <class T> void callfoo(T t) { foo(t); }

int main(int argc, char* argv[])
{
    int x = 3;
    callfoo(x);

    const char* p = "Hello world";
    callfoo(p); 

    return 0;
}

Это позволяет lib вызывать перегрузки для типов, о которых он фактически не знает до времени ссылки.

2 голосов
/ 08 октября 2011

Не могу сделать.Вы не можете иметь две переменные в одной области с одним и тем же именем.

1 голос
/ 08 октября 2011

Вы не можете сделать это с помощью указателей на функции ... список аргументов является частью типа, поэтому любой заданный указатель на функцию может соответствовать только одной конкретной перегрузке за раз.Вы можете подделать его с помощью функциональных объектов, однако, в зависимости от того, что вам нужно сделать.

struct MyPrint {
    void operator()(int i) { int_f(i); }
    void operator()(const char* c_str) { str_f(c_str); }

    std::function<void(int)> int_f;
    std::function<void(const char*) str_f;
};

void print_int(int i) { cout << i << endl; }
void print_string(const char* str) { cout << str << endl; }

int main() {
  MyPrint p;
  p.int_f = print_int;
  p.str_f = print_string;
  p(5);
  p("Hi");
}

Вы теряете способность просто перегружаться по имени;Вы не можете добавить set_functions(f), который принимает имя функции и извлекает обе версии функции.Но, как я показал, теперь вы не ограничены функциями с одинаковыми именами или даже просто функциями.Объект также больше, чем раньше, и, вероятно, включает в себя некоторые выделения кучи.

1 голос
/ 08 октября 2011

Указатель является типом, он не может быть перегружен.Только функции могут быть перегружены.

Нет способа добиться перегрузки указателя в C ++.

0 голосов
/ 08 октября 2011

Это может считаться "неуклюжим", но вы можете сделать что-то вроде следующего:

template<typename T>
struct funcptr_struct
{
    typedef T type;
    static type ptr;
};

template<> funcptr_struct<void(*)(int)>::type funcptr_struct<void(*)(int)>::ptr = myprint;
template<> funcptr_struct<void(*)(const char*)>::type funcptr_struct<void(*)(const char*)>::ptr = myprint;

Затем вы можете вызвать каждую версию функции myprint, используя синтаксис, подобный следующему:

funcptr_struct<void(*)(int)>::ptr(5);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...