Как вывести аргумент шаблона для лямбды при перегрузке функции?

#c #lambda #c 17 #function-templates-overloading

Вопрос:

Как я должен изменить свою текущую сигнатуру функции

 templatelt;class TypeData,typename TypeFunc1 = Identity,typename TypeFunc2gt; bool isPrime(const TypeDataamp; n,TypeFunc1 calcSqrt = {},TypeFunc2 isDivisible = [](const TypeDataamp; a,const TypeDataamp; b) {return a%b==0;},const bool debug = false)  

для того, чтобы быть вызванным из

 auto fSqrt = [](decltype(n) v) {return std::sqrt(static_castlt;floatgt;(v));}; std::coutlt;lt;(isPrime(n,fSqrt)?"Positive":"Negative")lt;lt;'n';  

Visual Studio 2019 дает

C2783 ‘bool isPrime(const TypeData amp;,TypeFunc1,TypeFunc2,const bool)’: не удалось вывести аргумент шаблона для ‘TypeFunc2’

Хотя и без этого все прекрасно TypeFunc2 isDivisible = [](const TypeDataamp; a,const TypeDataamp; b) {return a%b==0;} .

Каков правильный синтаксис для передачи лямбды по умолчанию?
Пожалуйста, помогите мне, пожалуйста.

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

1. Если один параметр шаблона имеет аргумент по умолчанию, то все параметры, следующие за ним, также должны иметь аргументы по умолчанию.

Ответ №1:

Проблема в том, что аргументы по умолчанию не способствуют вычету типов в параметрах шаблона.

Это можно показать на этом основном примере:

 template lt;typename Xgt; void f(X a = 2);  int main() {  f(); // The compiler spits out an error since it cannot determine the type 'X' holds }  

Что вам нужно будет сделать в этом сценарии, так это вместо этого использовать перегрузку функций:

 // ...  templatelt;class TypeData, typename TypeFunc1, typename TypeFunc2gt; bool isPrime(const TypeDataamp; n,  TypeFunc1 calcSqrt,  TypeFunc2 isDivisible,  const bool debug);  templatelt;class TypeDatagt; bool isPrime(const TypeDataamp; n) {  return isPrime(n, Identity{}, [](const TypeDataamp; a, const TypeDataamp; b) {  return a % b == 0;  }, false); }  // ...  

Ответ №2:

Ответ Рукса на самом деле очень хорош. Другой вариант-использовать функцию std::, она также может соответствовать вашим потребностям:

 templatelt;class TypeData,typename TypeFunc1=Identity,typename TypeFunc2 = std::functionlt;bool(const TypeDataamp;, const TypeDataamp;)gt;gt; bool isPrime(  const TypeDataamp; n,  TypeFunc1 calcSqrt = {},  TypeFunc2 isDivisible = [](const TypeDataamp; a,const TypeDataamp; b) {return a%b==0;},  const bool debug = false);  

Ответ №3:

Вам необходимо добавить тип по умолчанию для вашего TypeFunc2 , например:

 templatelt;class TypeData,  typename TypeFunc1 = Identity,  typename TypeFunc2 = bool(*)(const TypeDataamp;,const TypeDataamp;)gt;  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bool isPrime(const TypeDataamp; n,  TypeFunc1 calcSqrt = {},  TypeFunc2 isDivisible = [](const TypeDataamp; a,const TypeDataamp; b) {return a%b==0;},  const bool debug = false) {  // ... }