Я хочу написать лямбду, которая принимает произвольное количество аргументов по универсальной ссылке и полностью их игнорирует. Очевидным методом будет использование синтаксиса для универсального пакета параметров с переменными параметрами и опускание имени параметра:
auto my_lambda = [](auto&&...) { return 42; };
Это прекрасно работает (с GCC 4.9.2), пока я попробуйте передать нетривиально копируемый объект:
struct S { S() {} S(S const&) {} };
my_lambda("meow", 42, S{});
^ error: cannot pass objects of non-trivially-copyable type 'struct S' through '...'
В чем дело? Неправильный ли мой код или это ошибка в gcc?
В любом случае, какой лучший обходной путь? Я обнаружил, что присвоение имени параметру работает, но затем натолкнулся на предупреждение о неиспользованном параметре:
auto my_lambda = [](auto&&... unused) { return 42; };
^ error: unused parameter 'unused#0' [-Werror=unused-parameter]
^ error: unused parameter 'unused#1' [-Werror=unused-parameter]
^ error: unused parameter 'unused#2' [-Werror=unused-parameter]
Как вы подавляете предупреждение о неиспользованном параметре в пакете параметров шаблона?
Это ошибка разбора в GCC (о котором вы сами сообщили!). auto&&...
является грамматически неоднозначным и может быть проанализирован как эквивалент auto&&, ...
или объявление пакета параметров (технически, вопрос заключается в том, ...
является частью Параметр декларирование придаточного или абстрактно-описатель); стандарт говорит, что он должен быть проанализирован как последний; GCC разбирает это как первое.
Именование пакета разрешает неоднозначность анализа:
auto my_lambda = [](auto&&... unused) { return 42; };
Чтобы подавить предупреждение, можно применить __attribute__((__unused__))
(или, как предложил @Luc Danton, [[gnu::unused]]
):
auto my_lambda = [](auto&&... unused __attribute__((__unused__))) { return 42; };
или использовать sizeof...
auto my_lambda = [](auto&&... unused) { (void) sizeof...(unused); return 42; };
Других решений пока нет …