Home > front end >  How to deduce template argument for lambda, in function overload?
How to deduce template argument for lambda, in function overload?

Time:10-28

How should I modify my present function signature

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

in order to be called from

auto fSqrt = [](decltype(n) v) {return std::sqrt(static_cast<float>(v));};
std::cout<<(isPrime(n,fSqrt)?"Positive":"Negative")<<'\n';

Visual Studio 2019 gives

C2783 'bool isPrime(const TypeData &,TypeFunc1,TypeFunc2,const bool)': could not deduce template argument for 'TypeFunc2'

Everything fine without TypeFunc2 isDivisible = [](const TypeData& a,const TypeData& b) {return a%b==0;}, though.

What is the correct syntax for passing default lambda?
Kindly help me, please.

CodePudding user response:

The problem is that default arguments don't contribute to the deduction of types in template parameters.

This can be showed with this primary example:

template <typename X>
void f(X a = 2);

int main() {
    f(); // The compiler spits out an error since it cannot determine the type 'X' holds
}

What you'd need to do in this scenario is to use function overloading instead:

// ...

template<class TypeData, typename TypeFunc1, typename TypeFunc2>
bool isPrime(const TypeData& n,
             TypeFunc1 calcSqrt,
             TypeFunc2 isDivisible,
             const bool debug);

template<class TypeData>
bool isPrime(const TypeData& n) {
    return isPrime(n, Identity{}, [](const TypeData& a, const TypeData& b) {
            return a % b == 0;
        }, false);
}

// ...

CodePudding user response:

You need to add a default type for your TypeFunc2, for example:

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

CodePudding user response:

Ruks's answer is actually very good. Another option is to use std::function, it might suit your needs as well:

template<class TypeData,typename TypeFunc1=Identity,typename TypeFunc2 = std::function<bool(const TypeData&, const TypeData&)>>
bool isPrime(
    const TypeData& n,
    TypeFunc1 calcSqrt = {},
    TypeFunc2 isDivisible = [](const TypeData& a,const TypeData& b) {return a%b==0;},
    const bool debug = false);
  • Related