Гарантировано ли наличие operator() в C 11 lambda?

#c

#c

Вопрос:

Гарантируется ли работа этого кода с любым стандартным компилятором? Если это зависит от версии C , то от какой версии?

С технической точки зрения, гарантировано ли, что лямбда-выражение сгенерирует тип класса, и гарантированно ли, что класс, сгенерированный лямбдой, будет классом с уникальной функцией-членом ret_type operator()(arg_types...) , то есть при получении operator() адреса не возникает возможной двусмысленности перегрузки?

 template<typename T>
void f(T) {
  decltype(amp;T::operator()) ptr;
}

int main() {
  f([]() {});
}

  

Почему я хочу это сделать: я хочу получить типы аргументов lambda, которые я могу получить только со ссылкой на operator() because decltype , которые будут работать только для возвращаемого типа.

Конкретно то, что я пытаюсь сделать:

 myVariable.f([](Nameamp; name, Coloramp; color) {
  // Do something with arguments
});

// myVariable is some container with multiple data
// The lambda will take only the relevant data I want to have.
// I can also write this like it, but it's just about
// 1. Experiment some template things
// 2. "Hide" heavy template notation in caller code
// 3. Save some typing

myVariable.f<Name, Color>([](auto name, auto color) {
}); // How to transform this code into the first one ?

  

Комментарии:

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

2. Используете ли вы это в сочетании с std::invoke ?

3. » Я хочу получить типы аргументов lambda » Это не сработает, поскольку (после C 14) operator() может быть шаблоном . И вы не можете получить типы аргументов шаблона.

4. Я видел, что это возможно на en.cppreference.com/w/cpp/language/lambda но я не знаю, является ли это некоторым упрощением или действительно нравится в стандарте.

Ответ №1:

Вы можете посмотреть это в стандарте. В главе [expr.prim.lambda.closure] описывается, как выглядит сгенерированный тип замыкания. В пункте 1 говорится, что это класс:

1 Тип лямбда-выражения (которое также является типом объекта закрытия) — это уникальный, безымянный тип класса, не объединяемый, называемый типом закрытия, свойства которого описаны ниже.

В пункте 3 говорится, что оператор вызова функции будет присутствовать

3 Тип замыкания для лямбда-выражения имеет общедоступный оператор вызова встроенной функции (для неродового лямбда-выражения) или шаблон оператора вызова функции (для универсального лямбда-выражения) (12.6.4), параметры и тип возвращаемого значения которого описываются предложением объявления параметра лямбда-выражения и конечным типом возвращаемого значения соответственно, и список параметров шаблона которого состоит из указанного списка параметров шаблона, если таковой имеется.

Ссылка на 12.6.4 описывает, что оператор вызова функции действительно является operator () :

12.6.4 Вызов функции [over.call]
1 operator() должен быть нестатической функцией-членом с произвольным количеством параметров.

Как указал Николас, вопрос будет заключаться в том, есть ли у вас нестандартная лямбда, как в вашем примере, или универсальная лямбда (сравните дифференциацию в [expr.prim.lambda.closure] 3).

Комментарии:

1. У меня не будет шаблонной лямбды, параметры всегда будут явно известны (без auto), так что, я думаю, это тоже возможно. Спасибо вам.