Здравствуйте, waev, Вы писали:
W>то есть хочется писать примерно вот такой код:
W>W>typedef void (*pfun)(int a, int b = 7); // error!
W>void f1(int a, int b);
W>void main(){
W> pfun f = f1;
W> f(1);
W>}
W>
Конкретно здесь можно написать хитроумный указатель-на-функцию
struct pfun
{
typedef void result_type; // для std::bind
typedef result_type (*ptr_type)(int,int);
ptr_type p;
pfun(ptr_type p) : p(p) { assert(p); }
result_type operator() (int a, int b=7) const { return (*p)(a,b); }
};
Фактически, это мы дали уникальное имя типу void(int,int=7). И завернули туда вычисление необязательных аргументов. Сделали работу за компилятора.
Правда, мы не можем теперь привести pfun обратно к void(int,int) или void(int), или к точно такой же структуре, но под другим именем, — но можем привести и к std::function<void(int,int)>, и к std::function<void(int)>.
Почему это не поддержано в стандарте?
Во-первых, потому же, почему голый сишный указатель на функцию нельзя получить из std::function (наоборот — можно). Здесь не только семейство сигнатур описывается (void(int), void(int,int)), но и выражения для вычисления аргументов. А это уже в один указатель не вместится. Либо это будет указатель не на функцию, а на таблицу функций, или на какой-нибудь хитрый диспетчерский код. И никакой совместимости со старым добрым Си.
Во-вторых, поддержка этой фичи — это синтаксический сахар, сравнимый по объёму с лямбдами. Сколько лет потребовалось, чтобы лямбды в стандарт вошли? Сколько потребуется, чтобы ввести полиморфные лямбды? Вот то-то же. Если очень хочется, — нужно писать заявку в комитет и в ньюсгруппу.
Но это всё возвышенные рассуждения.
Практически, если такую фичу захотелось в конкретном месте, — то нужно глядеть в корень: ЗАЧЕМ её захотелось. Возможно, что там есть другие и не менее изящные решения в рамках нынешних возможностей.
Чисто в качестве альтернативы — совершенно не уверен, что это решает искомую задачу, но просто для иллюстрации, что так можно делать — введём не один, а два указателя рядом
void f1(int,int);
void f2(int,int);
int main()
{
void (*ff)(int,int) = (rand()%2 ? f1 : f2); // если мы захотим вызывать с 2 аргументами
std::function<void(int)> f = std::bind(ff, _1, 7); // если захотим вызывать с 1 аргументом
// если ff не нужен сам по себе - просто подставим его внутрь bind
f(1);
ff(1,2);
}