Как использовать перегруженные функции с аргументами по умолчанию в алгоритмах?

Я знаю ответ на часто задаваемый Как указать указатель на перегруженную функцию?: либо с назначением, либо с литым, и с любым другим С++ В этом руководстве вводятся строки, подобные этому (дайте или возьмите static_cast):

transform(in.begin(), in.end(), back_inserter(out), (int(*)(int)) std::toupper);

Или вот так:

int (*fp)(int) = std::toupper;
transform(in.begin(), in.end(), back_inserter(out), fp);

Что аккуратно выбирает перегрузку <cctype> std::toupper.

Но это задает вопрос: как я могу выбрать перегрузку <locale> аналогичным образом?

char (*fp2)(char, const std::locale&) = std::toupper;
transform(in.begin(), in.end(), back_inserter(out), fp2);
// error: too few arguments to function

Или, более практично, подумайте о том, кто пытается использовать С++ 11 std::stoi в алгоритме для преобразования вектора строк в вектор целых чисел: stoi имеет две перегрузки (string/wstring), каждый из которых принимает два дополнительных аргумента по умолчанию.

Предполагая, что я не хочу явно привязывать все эти значения по умолчанию, я считаю, что это невозможно сделать, не обертывая такой вызов вспомогательной функцией или лямбдой. Есть ли обертка или магия TMP, чтобы сделать это для меня полностью родовым образом? Может ли быть написана оболочка типа call_as<char(char)>(fp2) или, более вероятно, call_as<int(const std::string&)>(std::stoi)?

Ответ 1

Это смешно, я делал что-то подобное. Лучший способ, которым я нашел это, - использовать lambdas следующим образом, потому что в противном случае вам нужно использовать typedef для получения правильной перегрузки и std:: bind, чтобы избавиться от языкового стандарта или не использовать локаль. Однако это работает гораздо более чисто:

static const std::locale loc;
transform(in.begin(), in.end(), back_inserter(out), [&loc](char c) {
  return std::toupper(c, loc);
});

Я использую static для сохранения усилий перераспределения каждый раз.

Или вы можете получить typedef и сделать:

 std::bind((LocaleCompare)std::toupper, std::placeholders::_1, loc); // UGLY!

Ответ 2

Вы могли бы создать typedef этого типа указателя functon, а затем включить функцию.

typedef char (*LocaleToUpper)(char, const std::locale&) ;
char (*fp2)(char, const std::locale&) = (LocaleToUpper)toupper;