gpt4 book ai didi

c++ - 具有默认行为的函数指针

转载 作者:搜寻专家 更新时间:2023-10-31 02:22:10 24 4
gpt4 key购买 nike

在我的程序中,我有很多指向外部库提供的函数的指针。其中有些返回值,有些则没有。

如果外部库没有提供函数(指针为 NULL)并且函数应该返回值程序应该采用默认值(在编译时已知)。

我试图完成的是减少 if 语句的数量,并使用以下用例在类中包装指针:

enum E { e1, e2, e3 };
UserFunction<uint8_t(int, int), 0> callback1 { user_function_ptr }; // Calls and returns value of user_function_ptr
UserFunction<uint8_t(), 0> callback2 { nullptr }; // Returns 0
UserFunction<uint8_t(), 1> callback3 { nullptr }; // Returns 1
UserFunction<E(int), e1> callback4 { user_function_ptr2 }; // Returns enum value and takes one integer argument
UserFunction<void(int)> callback5 { user_function_ptr3 }; // No return value, one argument
UserFunction<void()> callback6 { nullptr }; // Should perform noop

到目前为止我得到的是为返回值的函数工作:

template <class Sign, int Def>
struct UserF;

template <class R, int Def, class... Args>
struct UserF<R(Args...), Def> {
typedef R Signature(Args...);
typedef typename std::add_pointer<Signature>::type SignaturePtr;

static R Default(Args... args) {
return (R) Def;
}

UserF() {
functionToCall = Default;
}

UserF(SignaturePtr userFunction) {
if (userFunction != nullptr) {
functionToCall = userFunction;
} else {
functionToCall = Default;
}
}

R operator() (Args... args) {
return functionToCall(args...);
}

private:
SignaturePtr functionToCall;
};

上面代码的问题在于它强制默认值为 int。我能做的是将 UserF 模板更改为如下所示:

template <class R, R Def, class... Args>
struct UserF {
// ...
};
// use case
UserF<E, e1, int> callback; // Returns E, takes int, default e1

但如果可能的话我宁愿使用

UserF<R(Args...), Default> callback; // preferred
UserF<Default, R(Args...)> callback; // if above is not possible
UserF<void(Args...)> callback; // if no return value

我宁愿不使用 std::function 因为我知道我将只处理指向函数的指针,而不是指向成员函数、仿函数对象等的指针。另外 boost 不是允许(允许 C++11)。

总而言之,问题是:如何强制对默认返回值进行类型检查。

最佳答案

template<class Sig>
struct return_type;
template<class Sig>
using return_type_t=typename return_type<Sig>::type;
template<class R,class...Args>
struct return_type<R(Args...)>{
using type=R;
};

template <class Sign, return_type_t<Sign> Def>
struct UserF;

是其中的大部分。要处理 void,您需要一个标志技巧:

struct void_flag{};
template<class T>
using flag_void=
typename std::conditional<std::is_same<T,void>{},void_flag*,T>::type;

template <class Sign, flag_void<return_type_t<Sign>> Def=nullptr>
struct UserF;

template <class R, R Def, class... Args>
struct UserF<R(Args...), Def>{
// body

template <class... Args>
struct UserF<void(Args...), 0>{
// body

非整数非指针 R 会出现问题,因为您不能将 double 传递给 template。一种方法是将 double 升级为 double const* for Def,并让它自动取消引用:

template <class R, R const* Def, class... Args>
struct UserF<R(Args...), Def>{
// body

并执行类似 flag_void 的操作,将 T=double 转换为 T=double const*

关于c++ - 具有默认行为的函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30617983/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com