c++ - 如何让 C++ 编译器间接推导 T?

标签 c++ templates

我的模板符比较弱。我有这段代码:

template<typename T>
void Foo(void(*func)(T*)) { }

void Callback(int* data) { }

int Test()
{
    Foo(Callback);
}

...但我想要比 C 的 void(*func)(T*) 讨厌的函数指针语法更具可读性的东西。

我团队中有人建议这样做:

template<typename T>
struct Types
{
    typedef void Func(T*);
};

template<typename T>
void Foo2(typename Types<T>::Func* func) {}

void Test2()
{
    Foo2(Callback);        // could not deduce template argument for 'T'
    Foo2<int>(Callback);   // ok
}

(我仍在争论这是否实际上更具可读性,但这是一个单独的问题。)

我怎样才能帮助编译器找出 T 是什么而不需要在调用者中明确指定它?

最佳答案

您可以使用特征类从函数类型中提取 T

template<class F>
struct CallbackTraits;

template<class T>
struct CallbackTraits<void(*)(T)>
{
    typedef T ArgumentType;
};

你的例子可以这样修改:

template<typename F>
void Foo(F func)
{
    typedef typename CallbackTraits<F>::ArgumentType T;
}

void Callback(int* data) { }

int Test()
{
    Foo(Callback);
}

boost type-traits 库中使用了此技术: http://www.boost.org/doc/libs/1_57_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html

这篇博文更详细地介绍了该技术的实现: https://functionalcpp.wordpress.com/2013/08/05/function-traits/

不幸的是,这种方法在 Foo 的签名中隐藏了关于传入参数的约束的信息。在上面的示例中,参数必须是 void(T*) 类型的函数

此替代语法与原始示例的作用相同,但可读性稍强:

template<typename T>
void Foo(void func(T*)) { }

另一种可能更具可读性的替代语法可以使用 c++11 的别名模板实现,如下所示:

template<typename T>
using Identity = T;

template<typename T>
void Foo(Identity<void(T*)> func) { }

不幸的是,最新的 MSVC 无法编译它,报告内部编译器错误。

关于c++ - 如何让 C++ 编译器间接推导 T?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27566409/

相关文章:

C++从文件中读取并比较魔数(Magic Number)

c++ - 通用引用,推断 std::list<T> 和 T

php - 如何在没有 PHP 脚本的 smarty 2.x 模板中分配关联数组值

c++ - 删除 CPropertySheet/Tabbed Dialog 页面下方的间隙

c++ - 遍历文件,只得到一行

c++ - 模板容器类被认为是 "scalar"?

c++ - "Extra Qualification on Member"模板类错误

Java:从模板和字典生成 XML 表

c++ - 指针引用类赋值

c++ - std::vector 行为、移动和复制