如何在 C++ 中将 void/null 作为默认参数添加到 function/lambda 指针?

How to add void/null as default argument to a function/lambda pointer, in C++?

现在的签名

template<class TypeData,typename TypeFunc>
bool isPrime(const TypeData& n,TypeFunc fSqrt,bool debug = false)

这与

完美配合
std::cout<<(isPrime(n,fSqrt)?"Positive":"Negative")<<'\n';

但是,我的意向是这样的

template<class TypeData,typename TypeFunc>
bool isPrime(const TypeData& n,TypeFunc fSqrt = nullptr,bool debug = false)

template<class TypeData,typename TypeFunc>
bool isPrime(const TypeData& n,TypeFunc fSqrt = NULL,bool debug = false)

调用
std::cout<<(isPrime(n)?"Positive":"Negative")<<'\n';

重载 是不可能的,因为函数内部有一个静态变量
只有不同的 class TypeData 应该为此 function-template.

提供不同的 template-functions

请帮我找出正确的语法。如果 C++ 不支持这个,我可以使用什么替代方法?

编译错误

对于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';
                       ^

对于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';
                       ^

基本相同

您可以使用具有正确原型的默认初始化 std::function

template<class TypeData>
bool isPrime(const TypeData& n,std::function<const decltype(n)&(const decltype(n)&)> fSqrt={},bool debug = false)

然后您可以通过 if (fSqrt)

检查函数是否有效或默认函数

完整示例:https://godbolt.org/z/zfMazebso

原型必须仅依赖于 n 的数据类型,否则可能没有默认参数,例如,编译器无法从无到有地推断出类型。

重载实际上一个选项,你可以让一个重载调用另一个:

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
    }
}

这个解决方案会立即选择一个合适的平方根函数,如果函数参数默认为 nullptr

您可以使用 std::identity 作为默认 TypeFunc 类型。

#include <functional>

template<class TypeData,typename TypeFunc = std::identity>
bool isPrime(const TypeData& n,TypeFunc fSqrt = {}, bool debug = false) {
  if constexpr (std::is_same_v<TypeFunc, std::identity>) return false;
  else {
    // ...
  }
}

Demo.

如果你的编译器不支持C++20,你可以简单地定义你自己的std::identity:

struct Identity {
  template<class T>
  constexpr decltype(auto) operator()(T&& t) const noexcept {
    return std::forward<T>(t);
  }
};