具有默认行为的函数指针
Function pointer with default behaviour
在我的程序中,我有很多指向外部库提供的函数的指针。其中一些返回值,其中一些则不返回值。
如果外部库没有提供函数(指针为 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
因为我知道我只会处理指向函数的指针,而不是指向成员函数、函子对象等的指针。也不允许提升(允许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*
以进行Def
,并使其自动取消引用:
template <class R, R const* Def, class... Args>
struct UserF<R(Args...), Def>{
// body
并做一些像flag_void
这样的事情,把T=double
变成T=double const*
.
如果你能忍受一个小宏,你可以这样做:
template <typename sig, typename T, T v >
struct UserF_;
template <class R, typename ... Args, typename T, T v >
struct UserF_< R(Args...), T, v > {
// ...
};
#define UserF( F, Default ) UserF_< F, decltype( Default ), Default >
UserF(R(Args...), Default) callback;
如果不先将泛型模板非类型参数的类型指定为模板类型参数,则不能具有该参数。
相关文章:
- QMetaObject invokeMethod的基于函数指针的语法
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- c++r值引用应用于函数指针
- 模板函数指针和lambda
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 带有类的函数指针
- () 函子后面的括号,而不是函数指针?
- 全局作用域中函数指针的赋值
- 使用"Task"函数指针队列定义作业管理器
- 将成员函数指针作为参数传递给模板方法
- 如何创建对象函数指针C++映射?
- 匹配函数指针作为模板参数?
- 通过函数指针定义类范围之外的方法
- 存储在类中的函数指针
- C++从函数指针数组调用函数
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 整数键映射到头文件中的成员函数指针
- 从类成员函数到类 C 函数指针的转换
- 如何将内联匿名函数分配给C++函数指针
- 将字符缓冲区强制转换为函数指针