如何使用函数的参数类型编写可以推断类型的模板?
How to write a template that can deduce a type use a function's argument type?
如何编写一个使用函数作为模板参数的模板,并通过该函数的参数类型自动推导出其他类型名?
void foo(int *p) {}
template<typename T, void (*F)(T*)>
struct bar
{
bar(T* t)
{
F(t);
}
}
int *p;
bar<int, foo> b(p); // both int and foo are required here
如何编写支持仅使用foo
作为参数的模板
bar<foo> b(p);
如果您可以将 c++17 与它的自动模板参数一起使用(如注释中所说的 @n.m.),您可以将其用作模板参数,然后是具有类型特征的 T 类型。
首先,我们需要标准类型特征和一个类型特征,以便将参数转换为一元函数(您的 foo),我们可以这样编写:
#include <type_traits>
// Trait to get the argument type of a unary function
template<typename T>
struct unary_func_arg;
template<typename R, typename T>
struct unary_func_arg< R(*)(T) >
{
using type = T;
};
如果将函数指针以外的任何内容放入其中,这将产生错误,因为未声明主要专用化。
在此之后,我们最终可以这样写 bar:
template< auto F >
struct bar
{
// Assert it's a function pointer
static_assert( std::is_pointer_v<decltype(F)> );
static_assert( std::is_function_v< std::remove_pointer_t<decltype(F)> > );
// Get the parameter type
using T = typename unary_func_arg< decltype(F) >::type;
bar(T t)
{
F(t);
}
};
我们必须确保 F 是一个函数指针,所以我们静态断言,然后我们从类型特征中获取类型 T。
现在你可以像这样声明 f 和 b:
int* p;
bar<foo> b(p);
编辑:如果你需要T不是指针,所以你可以写T*,你可以做一个类型特征来删除1个指针级别,或者修改这里的类型特征,这样:
// Trait to get the argument type of a unary function
template<typename T>
struct unary_func_arg_pointer;
template<typename R, typename T>
struct unary_func_arg_pointer< R(*)(T*) >
{
using type = T;
};
现在在这个例子中 T 将只是 int
在 C++11 中,类无法推导出传递函数的所有类型的类型。但是一个函数可以。所以这个函数可以写成:
template<typename Ret, typename Param>
Deduced_Types<Ret, Param> deduce_type(Ret (*)(Param))
{
return Deduced_Types<Ret, Param>();
}
此函数使用类型来存储推导的类型(必须在函数之前声明):
template<typename Ret, typename Param>
class Deduced_Types
{
public:
typedef Ret Return_type;
typedef Param Parameter_type;
};
现在测试它;
int f(bool)
{
return 0;
}
int main(int argc, char* argv[])
{
decltype( deduce_type(f) )::Return_type i = 0;
return i;
}
它有效。
所以现在要酒吧:
template< class F >
class Bar
{
public:
typedef typename F::Return_type Func_Return_type;
typedef typename F::Parameter_type Fun_Param_type;
};
必须称为:
Bar< decltype(deduce_type(f)) > b;
(这是您可以使用宏的地方)
适用于 gcc 4.8.1 : https://godbolt.org/z/1cz2pk
编辑:
C++17 之前的函数无法传递到模板中。
所以需要的是你需要将函数指针传递到类中。以及验证参数是否正确static_assert
:
#include <type_traits>
struct bar
{
template<typename F, typename T>
bar(F f, T t)
{
typedef decltype(deduce_type(f)) D;
static_assert(std::is_same<typename D::Parameter_type, T>::value,"parameter has different type function parameter");
f(t);
}
};
现在,函数指针不是作为模板参数传递,而是作为参数传入:
void foo(int *p) {}
int *p;
bar b(foo, p);
这里唯一的问题是类必须存储此指针以供将来使用。
在 C++17 中,您可能会这样做
template <auto> struct bar;
template<typename T, void (*F)(T*)>
struct bar<F>
{
bar(T* t) { F(t); }
};
用法:
int* p = nullptr;
bar<foo> b(p);
在 C++17 之前,您可能会执行以下操作:
template <typename T, T> struct bar;
template<typename T, void (*F)(T*)>
struct bar<void (*)(T*), F>
{
bar(T* t) { F(t); }
};
使用:
int* p = nullptr;
bar<decltype(&foo), &foo> b(p);
宏可用于删除重复项,例如:
#define BAR(Func) bar<decltype(&Func), &Func>
#define TYPE_AND_VALUE(V) decltype(V), V>
以允许:
BAR(foo) b(p);
bar<TYPE_AND_VALUE(&foo)> b(p);
- 特征::矩阵<双精度,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 文件名吗?