推导 typedef'd 函数指针的模板参数

deduce template argument for typedef'd function pointer

本文关键字:指针 参数 函数 typedef 推导      更新时间:2023-10-16

在使用typedef时,是否有方法推导函数指针的模板参数?我的示例代码是:

struct A {};
void func(const A&) {};
template <typename T>
struct FuncPtr
{
    typedef void(*Type)(const T&);
};
void f_(FuncPtr<A>::Type) {}
template <typename T> // I'd like to hide the messy function pointer in a typedef
void f1(typename FuncPtr<T>::Type fp) { f_(fp); }
template <typename T> // this works, but "fp" is really several lines long
void f2(void(*fp)(const T&)) { f_(fp); }

有了这个,我可以打电话给f2(AFunc)。但我更喜欢f1(func),因为在我的实际代码中,函数指针的声明要长得多。我需要一个实际的函数指针,而不仅仅是传递一个模板参数,这样我就可以调用f_()

当前设置不适用。::*左边的所有内容都是非推导上下文,因为元函数可以对类型应用任意的图灵完全变换,并且在任何情况下,原始类型和结果之间都没有保证的一对一映射。所以这种语言甚至没有尝试。

但别名模板会起作用:

template <class T>
using FuncPtr = void (*)(const T&);
template <typename T>
void f3(FuncPtr<T> fp) { return f_(fp); }

*正式称为"使用限定id指定的类型的嵌套名称说明符"([temp.dexect.type]/p5)。

作为"有效的现代C++"第9项,与typedefs相比,更喜欢别名声明:

特别是,别名声明可以模板化(在这种情况下它们被称为别名模板),而typedef则不能。这给C++11程序员一种简单的表达机制在C++98中,必须与嵌套在里面的typedef一起被破解模板化结构。例如,考虑为使用自定义分配器MyAlloc的链表定义一个同义词。有了别名模板,这就是小菜一碟:

template<typename T
using MyAllocList = std::list<T, MyAlloc<T>>;
MyAllocList<Widget> lw; 

使用typedef,您几乎必须从划痕:

template<typename T> 
struct MyAllocList { 
 typedef std::list<T, MyAlloc<T>> type; 
}; 
MyAllocList<Widget>::type lw;