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

Sup*_*eto 10 c++ templates pointers function-pointers default-arguments

目前的签名

\n
template<class TypeData,typename TypeFunc>\nbool isPrime(const TypeData& n,TypeFunc fSqrt,bool debug = false)\n
Run Code Online (Sandbox Code Playgroud)\n

这与

\n
std::cout<<(isPrime(n,fSqrt)?"Positive":"Negative")<<'\\n';\n
Run Code Online (Sandbox Code Playgroud)\n

但是,我的意图是这样的

\n
template<class TypeData,typename TypeFunc>\nbool isPrime(const TypeData& n,TypeFunc fSqrt = nullptr,bool debug = false)\n
Run Code Online (Sandbox Code Playgroud)\n

或者

\n
template<class TypeData,typename TypeFunc>\nbool isPrime(const TypeData& n,TypeFunc fSqrt = NULL,bool debug = false)\n
Run Code Online (Sandbox Code Playgroud)\n

被称为

\n
std::cout<<(isPrime(n)?"Positive":"Negative")<<'\\n';\n
Run Code Online (Sandbox Code Playgroud)\n

由于函数内部有静态变量,因此不可能重载。
\n只有不同才应该为此function-templateclass TypeData提供不同的template-functions

\n

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

\n

编译错误

\n

为了TypeFunc fSqrt = nullptr

\n
main.cpp:90:23: error: no matching function for call to \xe2\x80\x98isPrime(int&)\xe2\x80\x99\n  std::cout<<(isPrime(n)?"Positive":"Negative")<<'\\n';\n                       ^\nmain.cpp:9:49: note: candidate: template bool isPrime(const TypeDate&, TypeFunc, bool)\n template<class TypeDate,typename TypeFunc> bool isPrime(const TypeDate& n,TypeFunc fSqrt = nullptr,bool debug = false) {\n                                                 ^~~~~~~\nmain.cpp:9:49: note:   template argument deduction/substitution failed:\nmain.cpp:90:23: note:   couldn't deduce template parameter \xe2\x80\x98TypeFunc\xe2\x80\x99\n  std::cout<<(isPrime(n)?"Positive":"Negative")<<'\\n';\n                       ^\n
Run Code Online (Sandbox Code Playgroud)\n

为了TypeFunc fSqrt = NULL

\n
main.cpp:90:23: error: no matching function for call to \xe2\x80\x98isPrime(int&)\xe2\x80\x99\n  std::cout<<(isPrime(n)?"Positive":"Negative")<<'\\n';\n                       ^\nmain.cpp:9:49: note: candidate: template bool isPrime(const TypeDate&, TypeFunc, bool)\n template<class TypeDate,typename TypeFunc> bool isPrime(const TypeDate& n,TypeFunc fSqrt = NULL,bool debug = false) {\n                                                 ^~~~~~~\nmain.cpp:9:49: note:   template argument deduction/substitution failed:\nmain.cpp:90:23: note:   couldn't deduce template parameter \xe2\x80\x98TypeFunc\xe2\x80\x99\n  std::cout<<(isPrime(n)?"Positive":"Negative")<<'\\n';\n                       ^\n
Run Code Online (Sandbox Code Playgroud)\n

它们基本上是相同的。

\n

康桓瑋*_*康桓瑋 6

您可以将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 {
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

演示。

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

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


Aco*_*gua 3

重载实际上一种选择,您可以让一个重载调用另一个重载:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

该解决方案立即选择合适的平方根函数,如果函数参数默认为 ,则无论如何您都必须解决这个问题nullptr