Present signature is
template<class TypeData,typename TypeFunc>
bool isPrime(const TypeData& n,TypeFunc fSqrt,bool debug = false)
and this works perfectly with
std::cout<<(isPrime(n,fSqrt)?"Positive":"Negative")<<'\n';
But, my intension is something like
template<class TypeData,typename TypeFunc>
bool isPrime(const TypeData& n,TypeFunc fSqrt = nullptr,bool debug = false)
or
template<class TypeData,typename TypeFunc>
bool isPrime(const TypeData& n,TypeFunc fSqrt = NULL,bool debug = false)
to be called by
std::cout<<(isPrime(n)?"Positive":"Negative")<<'\n';
Overloading is not possible due to a static variable inside the function.
Only different class TypeData
should give different template-functions for this function-template.
Please help me out with the proper syntax. If C++ does not support this, what is an alternative approach I can use?
Compile Errors
for TypeFunc fSqrt = nullptr
main.cpp:90:23: error: no matching function for call to ‘isPrime(int&)’
std::cout<<(isPrime(n)?"Positive":"Negative")<<'\n';
^
main.cpp:9:49: note: candidate: template bool isPrime(const TypeDate&, TypeFunc, bool)
template<class TypeDate,typename TypeFunc> bool isPrime(const TypeDate& n,TypeFunc fSqrt = nullptr,bool debug = false) {
^~~~~~~
main.cpp:9:49: note: template argument deduction/substitution failed:
main.cpp:90:23: note: couldn't deduce template parameter ‘TypeFunc’
std::cout<<(isPrime(n)?"Positive":"Negative")<<'\n';
^
for TypeFunc fSqrt = NULL
main.cpp:90:23: error: no matching function for call to ‘isPrime(int&)’
std::cout<<(isPrime(n)?"Positive":"Negative")<<'\n';
^
main.cpp:9:49: note: candidate: template bool isPrime(const TypeDate&, TypeFunc, bool)
template<class TypeDate,typename TypeFunc> bool isPrime(const TypeDate& n,TypeFunc fSqrt = NULL,bool debug = false) {
^~~~~~~
main.cpp:9:49: note: template argument deduction/substitution failed:
main.cpp:90:23: note: couldn't deduce template parameter ‘TypeFunc’
std::cout<<(isPrime(n)?"Positive":"Negative")<<'\n';
^
They are basically the same.
Overloading actually is an option, you can let one overload call the other one:
template<class TypeData, typename TypeFunc>
bool isPrime(const TypeData& n, TypeFunc fSqrt, bool debug = false);
template<class TypeData>
bool isPrime(const TypeData& n, bool debug = false)
{
using std::sqrt;
if constexpr (std::is_integral_v<TypeData>)
{
return isPrime(n, static_cast<double(*)(double)>(sqrt), debug);
}
else if constexpr (std::is_floating_point_v<TypeData>)
{
return isPrime(n, static_cast<TypeData(*)(TypeData)>(sqrt), debug);
}
else
{
// this covers e.g. std::complex
return isPrime(n, static_cast<TypeData(*)(TypeData const&)>(sqrt), debug);
// for any other type we assume the overload accepts by
// const reference as well (if there's one at all...)
// if not, we still can fall back to the other overload
}
}
This solution selects an appropriate square root function right away, something you would have had to solve anyway if the function argument had defaulted to nullptr
.