如何在 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 {
// ...
}
}
如果你的编译器不支持C++20,你可以简单地定义你自己的std::identity
:
struct Identity {
template<class T>
constexpr decltype(auto) operator()(T&& t) const noexcept {
return std::forward<T>(t);
}
};
现在的签名是
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.
请帮我找出正确的语法。如果 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 {
// ...
}
}
如果你的编译器不支持C++20,你可以简单地定义你自己的std::identity
:
struct Identity {
template<class T>
constexpr decltype(auto) operator()(T&& t) const noexcept {
return std::forward<T>(t);
}
};