c++ - 坚持使用 C++ 元编程
问题描述
我正在尝试通过一本名为Practical C++ Metaprogramming的书进入 TMP,但我一直在尝试推导出第一个示例...
我的目标是制作一个模板化函数call
,该函数采用具有多个不相关类型参数的函数,然后返回带有参数的该函数的计算。
问题的根源似乎是我无法在我的代码中使用适当的参数类型来实例化一个结构(良好的专业化),这将允许我在我的代码makeTupleOfParams
中定义输入函数参数的类型。tupleOfParamTypes_t
我不明白为什么会出现这个问题,因为构建输出中的 Function 签名似乎模棱两可,足以识别具有 specialization 的参数的类型<Return(Args...)>
。我不明白为什么这个结构不会用正确的成员生成,using type = std::tuple<Args...>;
这似乎是所有这一切的关键。
这是整个事情:
#include <tuple>
// base template
template<typename Function>
struct makeTupleOfParams;
// template specialization to identify parameters
template <typename Return, typename... Params>
struct makeTupleOfParams<Return(Params...)>
{
using type = std::tuple<Params...>;
};
// shortcut to identify type of parameters
template <typename Function>
using tupleOfParamTypes_t = typename makeTupleOfParams<Function>::type;
// function to unroll a tuple of parameters on a function
template <typename Function, typename Params, size_t... Index>
auto dispatchParams(Function f, Params p, std::index_sequence<Index...>)
{
return f(std::get<Index>(p)...);
}
template <typename Function, typename... Params>
auto call(Function f, Params... p)
{
// getting size of Params and argument types of Function
constexpr size_t paramsCount = sizeof...(Params);
tupleOfParamTypes_t<Function> params;
return dispatchParams(f, params, std::make_index_sequence<paramsCount>());
}
auto f(int i, float j) -> decltype(i+j)
{
return i + j;
};
void main()
{
call(f, 1, 2.0);
}
和构建输出:
1 > ------Build started : Project: TMP, Configuration : Debug Win32------
1 > main.cpp
1 > d:\git\meta - cpp - sandbox\src\main.cpp(40) : warning C4326 : return type of 'main' should be 'int' instead of 'void'
1 > d:\git\meta - cpp - sandbox\src\main.cpp(16) : error C2794 : 'type' : is not a member of any direct or indirect base class of 'makeTupleOfParams<Function>'
1 > with
1 > [
1 > Function = float(__cdecl *)(int, float)
1 > ]
1 > d:\git\meta - cpp - sandbox\src\main.cpp(28) : note: see reference to alias template instantiation 'tupleOfParamTypes_t<float(__cdecl *)(int,float)>' being compiled
1 > d:\git\meta - cpp - sandbox\src\main.cpp(41) : note: see reference to function template instantiation 'auto call<float(__cdecl *)(int,float),int,double>(Function,int,double)' being compiled
1 > with
1 > [
1 > Function = float(__cdecl *)(int, float)
1 > ]
1 > d:\git\meta - cpp - sandbox\src\main.cpp(26) : error C2938 : 'tupleOfParamTypes_t' : Failed to specialize alias template
1 > d:\git\meta - cpp - sandbox\src\main.cpp(31) : error C2672 : 'dispatchParams' : no matching overloaded function found
1 > d:\git\meta - cpp - sandbox\src\main.cpp(26) : error C2893 : Failed to specialize function template 'auto dispatchParams(Function,Params,std::integer_sequence<unsigned int,_Ix...>)'
1 > d:\git\meta - cpp - sandbox\src\main.cpp(26) : note: With the following template arguments :
1 > d:\git\meta - cpp - sandbox\src\main.cpp(26) : note: 'Function=float (__cdecl *)(int,float)'
1 > d:\git\meta - cpp - sandbox\src\main.cpp(26) : note: 'Params=unknown-type'
1 > d:\git\meta - cpp - sandbox\src\main.cpp(26) : note: 'Index={0, 1}'
1 > Done building project "TMP.vcxproj" --FAILED.
========== Build: 0 succeeded, 1 failed, 0 up - to - date, 0 skipped ==========
解决方案
当你调用你的call
函数时,你将函数f
作为参数传递。但是 c++ 隐式地将参数转换为指向函数的指针。因此,在构造类型别名时,模板参数实际上是int(*)(int,float)
,而不是int(int,float)
。由于这不满足部分特化模板的要求,编译器尝试从非特化模板为 makeTupleOfParams 构造类型别名。但是,非专用模板不包含类型别名“type”,这会导致编译错误。
要解决此问题,请将部分专业化的模板修改为:
template<typename Return, typename... Params>
struct makeTupleOfParams<Return(*)(Params...)> //pointer-to-function specialisation
{
using type = std::tuple<Params...>;
};
另一种解决方案是用于type_traits
删除call
函数中的指针特征,如下所示:
#include<type_traits>
template <typename Function, typename... Params>
auto call(Function f, Params... p)
{
// getting size of Params and argument types of Function
constexpr size_t paramsCount = sizeof...(Params);
// modify function type to remove pointer trait
tupleOfParamTypes_t<std::remove_pointer_t<Function>> params;
return dispatchParams(f, params, std::make_index_sequence<paramsCount>());
}
在这种情况下,传递给的模板参数tupleOfParamTypes_t
将是int(int,float)
.
推荐阅读
- angular - ngIf 在 BSDropdown 上
- javascript - 从 bpmn Moodle 中的异步函数中检索对象
- python - 通过服务更换壁纸的问题
- bixby - 在 Bixby 模拟器中,是否可以在开发配置和生产配置之间切换?
- php - 当值为真时,PHP if else 语句不执行代码
- javascript - 如何将对象从视图传递到 ASP.NET MVC 中的控制器?
- javascript - 将输入数据从子级传递给父级 React.js
- python - 包括函数的循环,因此如果数字不正确,它可以要求用户重新输入数字
- swift5 - WooCommerce Rest API JSON formate Complex implementation in Swift
- react-final-form - 当使用 react-final-form 从表单数组中删除元素时,显示的值不会更新,但最终形式的数据对象会