从函数参数推断模板类型
Infering template type from function argument
我不确定问题的标题,但基本上我很好奇如何创建一个类似访问者的函数,该函数可以对正确使用类型推断的集合上的某些类型进行操作。
例如,集合包含从单个基类 (Base
) 继承的对象。某些操作仅适用于特定的子类(例如,FooBar
继承自Base
)。
一个实现可以是
template<class T, class F>
void visit(F f)
{
for (auto c : the_collection) {
if (auto t = dynamic_cast<T*>(c)) {
f(t);
}
}
}
这里的问题是调用这样的函数需要指定类类型FooBar
两次:
visit<FooBar>([](FooBar* f) { f->some_method(); });
我想使用类型推断,所以我可以写visit([](FooBar* f) ...
,但无法获得正确的模板。
例如:
template<class T>
using Visitor = std::function<void(T*)>;
template<class T>
void visit(const Visitor<T>& f)
{
for (auto c : the_collection)
if (auto t = dynamic_cast<T*>(c))
f(t);
}
适用于visit<FooBar>([](FooBar*) ...
,但不适用于visit([](FooBar*) ...
。
找不到匹配的重载函数
void visit(const std::function<void(T> &)':无法从 '{....}::
推断出 'const std::function<void(T> &' 的模板参数
是否可以定义一个可以以这种方式推断类型的模板,或者语言规范不允许这样做?
您标记了C++17,因此您可以使用演绎指南进行std::function
。
那么下面这样的事情呢?
template <typename>
struct first_arg_type;
template <typename R, typename T0, typename ... Ts>
struct first_arg_type<std::function<R(T0, Ts...)>>
{ using type = T0; };
template <typename F>
void visit (F const & f)
{
using T = typename first_arg_type<decltype(std::function{f})>::type;
for (auto c : the_collection)
if (auto t = dynamic_cast<T>(c))
f(t);
}
请注意,您可以使用标准类型first_argument_type
而不是自定义类型特征first_arg_type
std::function
,因此
using T = typename decltype(std::function{f})::first_argument_type;
不幸的是,std::function::first_argument_type
从 C++17 开始被弃用,并将从 C++20 中删除。
到目前为止,我发现最简单的方法(但不完全是我一直在寻找的)是使用问题中指示的第二种形式定义访问者,并将 lambda 参数声明为auto
:
template<class T>
using Visitor = std::function<void(T*)>;
template<class T>
void visit(const Visitor<T>& f)
{
for (auto c : the_collection)
if (auto t = dynamic_cast<T*>(c))
f(t);
}
// ...
visit<FooBar>([](auto f) { f->some_method(); });
我们可以通过推导 lambda 的调用运算符的类型来实现所需的visit([](FooBar*){ /*...*/ });
语法。
template <typename Element, typename Class, typename Parameter>
void call(Element element, Class *callable, void(Class::*function)(Parameter) const) {
if (auto parameter = dynamic_cast<Parameter>(element)) {
(callable->function)(parameter);
}
}
template <typename Functor>
void visit(Functor &&functor) {
for (auto element : the_collection) {
call(element, &functor, &Functor::operator());
}
}
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 将C++子类成员函数(虚拟实现)传递给 C 类型函数指针
- C++ 这里有一个返回 (24) 的布尔返回类型函数
- 使用SFINAE来检测void返回类型函数的存在
- 使用此类型函数有什么优势
- 为什么此函数通过类型函数指针调用后,呼叫明智地行为
- 如何使用无类型函数指针调用C++成员函数
- 模板返回类型函数如何在C++中工作
- 具有通用类型函数的动态库[C ]
- 如何在返回类型函数模板的专用化中使用派生类型?( "couldn't infer template argument" )
- Bon appetit :从 int 返回类型函数在 main() 中打印字符串
- 对于需要其他模板参数的类型函数的部分模板专业化
- c++错误的参数类型-函数指针
- 延迟评估模板类型函数
- 在引用或指针返回类型函数上输入
- 具有指针数据类型的非类型函数模板参数
- STL中使用的C++自定义比较类型(函数谓词与较少结构)
- C++模板基类的非类型函数模板的 using 声明
- 字符串到类型函数,模板专用化使调用统一
- 自由类型函数可以接受 Unicode 文件名吗?