【发布时间】:2021-02-19 17:50:03
【问题描述】:
我有一个回调对象的类型层次结构。经过大量的简化后,它看起来有点像这样:
template <typename Return, typename... Args>
struct Callback
{
virtual Return Call(Args...) =0;
void* mCtx;
}; // ctor, virtual dtor omitted
template <class T, typename Return, typename... Args>
struct MemberCallback: Callback<Return, Args...>
{
Return Call(Args... args) override
{
return (static_cast<T*>(mCtx)->*mFn)(args...);
}
Return(T::*mFn)(Args...);
}; // ctor, specialisation for Return = void omitted
template <typename Return, typename... Args>
struct FunctionPtrCallback: Callback<Return, Args...>
{
Return Call(Args... args) override
{
return mFn(args..., mCtx);
}
Return(*mFn)(Args..., void*);
}; // ctor, specialisation for Return = void omitted
还有一个工厂函数来推断MemberCallback<>s的类型:
template <class T, typename Return, typename... Args>
MemberCallback<T, Return, Args...> MakeCallback(T& object, Return(T::*fn)(Args...))
{
return MemberCallback<T, Return, Args...>(&object, fn);
} // overload for const methods omitted
我正在尝试为FunctionPtrCallback<>s 设置类似的工厂函数,但是我一直遇到错误:
幼稚的方法FunctionPtrCallback<Return, Args...> MakeCallback(Return(*fn)(Args..., void*), void*) 在未能从void (ActualTypeUsed,void *) (C2784) 推断出Return (__cdecl *)(Args...,void *) 的模板参数后,会抱怨未能找到合适的重载 (C2672)。
编辑:明确指定模板参数 - MakeCallback<void, ActualTypeUsed> 将使其编译,除了只接受单个 void* (MakeCallback<void>()) 的函数。
(如果我在 MakeCallback 声明中从 fn 的签名中省略了 void* 参数,它会编译,但会实例化错误的 FunctionPtrCallback 模板 - FunctionPtrCallback<void, ActualTypeUsed, void*> 而不是 FunctionPtrCallback<void, ActualTypeUsed>。)
然后我尝试使用临时“功能特征”模板,类似于https://stackoverflow.com/a/9065203/79344 中建议的模板:
template <typename T>
struct FnTraits;
template <typename Return, typename... Args>
struct FnTraits<Return(Args...)>
{
FunctionPtrCallback<Return, Args...> MakeCallback(Return(*fn)(Args..., void*), void* data)
{
return FunctionPtrCallback<Return, Args...>(fn, data);
}
};
现在投诉是关于在我的FnTraits<decltype(MyCallback)>::MakeCallback(MyCallback, myData) 的嵌套名称说明符中使用不完整类型。将 MyCallback 的声明放在 FnTraits<> 之前(但不切实际)也无济于事。
1,用简洁的学术术语来说,为什么我的方法是错误的/我对模板推导有什么误解?
2,如果有办法让它工作,从我的回调中自动推断出Return 和Args...,它是什么?
(我知道std::function<>;我宁愿避免使用它。)
编辑:godbolt link
【问题讨论】:
-
你能提供一个minimal reproducible example,或者godbolt.org链接吗?
-
@jtbandes 现在添加了一个。
标签: c++ templates function-pointers type-deduction