Как перегрузить простую локальную лямбда-функцию?
SSE оригинальной задачи:
#include <iostream>
#include <map>
void read()
{
static std::string line;
std::getline(std::cin, line);
auto translate = [](int idx)
{
constexpr static int table[8]{ 7,6,5,4,3,2,1,0 };
return table[idx];
};
auto translate = [](char c)
{
std::map<char, int> table{ {'a', 0}, {'b', 1}, {'c', 2}, {'d', 3},
{'e', 4}, {'f', 5}, {'g', 6}, {'h', 7} };
return table[c];
};
int r = translate(static_cast<int>(line[0]));
int c = translate(static_cast<char>(line[1]));
std::cout << r << c << std::endl;
}
int main()
{
read();
return 0;
}
Сообщения об ошибках
error: conflicting declaration 'auto translate'
note: previous declaration as 'read()::<lambda(int)> translate'
Пожалуйста, не возражайте против проверки ввода пользователя, это SSE.
c++
lambda
overloading
c++17
function-object
выслеживающий
источник
источник
translate
это просто локальные переменные, которые не могут использовать одно и то же имя.Ответы:
Нет нельзя лямбду перегружать!
Лямбды - это анонимные функторы (т. Е. Объекты без имен), а не простые функции. Поэтому перегрузка этих объектов невозможна. То, что вы в основном пытаетесь сделать, это почти
Что невозможно, так как одно и то же имя переменной нельзя использовать в C ++.
Тем не менее, в c ++ 17 мы имеем
if constexpr
возможность создавать единственную ветвь, которая является истинной во время компиляции.Имеются в виду возможные решения:
decltype
дляif constexpr
проверки. ( Credits @NathanOliver )Используя шаблон variabe вы можете сделать что-то вроде. ( Смотрите живую демоверсию онлайн )
и называть это как
Используя общую лямбду (начиная с c ++ 14 ), выше будет: ( см. Живую демонстрацию онлайн )
и позвоните в лямбду, как вы делаете сейчас:
источник
else if
должны бытьelse if constexpr
. Во-вторых, зачем использовать шаблон переменной? Вы могли бы просто сделать лямбду-родовой, и ваши чеклы стали быif constexpr (std::is_same_v<decltype(idx), int>)
иelse if constexpr (std::is_same_v<decltype(idx), char>)
Лямбды в основном являются синтаксическим сахаром для локально определенных функторов. Насколько я знаю, они никогда не предназначались для перегрузки для вызова с другими параметрами. Обратите внимание, что каждое лямбда-выражение относится к разному типу, поэтому даже в случае непосредственной ошибки ваш код не может работать так, как задумано.
Однако вы можете определить функтор с перегруженным
operator()
. Это будет именно то, что вы получите от лямбд, если бы это было возможно. Вы просто не получаете краткий синтаксис.Что-то вроде:
источник
Таким образом, правила перегрузки имен применяются только к определенным видам поиска имен функций. (как свободных, так и методов).
Лямбды не являются функциями, это объекты с оператором вызова функции. Таким образом, перегрузка не может возникнуть между двумя разными лямбдами.
Теперь вы можете получить разрешение перегрузки для работы с функциональными объектами, но только в пределах одного объекта. И тогда, если есть более одного
operator()
, разрешение перегрузки может выбирать между ними.У лямбды, однако, нет очевидного способа иметь более одного
operator()
. Мы можем написать простой (на с ++ 17 ) вспомогательный класс, который поможет нам:и руководство по удержанию:
с этими двумя мы можем перегрузить две лямбды:
и сделано.
Запись
overloaded
возможна как на c ++ 14, так и на c ++ 11, но требует больше работы и менее элегантна. Как только вы узнаете о проблеме, найти решение, которое будет соответствовать тому, что поддерживает ваш конкретный компилятор, с помощью функций C ++, не составит труда.источник
variadic generic lamda
+if constexpr
для разделения звонков?