首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >坚持使用C++元编程

坚持使用C++元编程
EN

Stack Overflow用户
提问于 2020-04-22 08:49:56
回答 1查看 68关注 0票数 0

我正试图通过一本名为Practical C++ Metaprogramming的书进入TMP,我被困在试图推导出第一个例子中的一个……

我的目标是创建一个带有多个无关类型参数的函数的模板函数call,然后用这些参数返回该函数的计算结果。

问题的根源似乎是我无法用适当的参数类型实例化一个结构(makeTupleOfParams的良好专门化),该参数类型允许我在代码中定义输入函数参数的类型,即tupleOfParamTypes_t

我不明白为什么会出现这样的问题,因为构建输出中的函数签名似乎足够模棱两可,足以用专门化<Return(Args...)>来识别参数的类型。我不明白为什么这个结构不能用正确的成员using type = std::tuple<Args...>;生成,这似乎是所有这一切的关键。

整个过程是这样的:

代码语言:javascript
运行
复制
#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);
}

和构建输出:

代码语言:javascript
运行
复制
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 ==========
EN

Stack Overflow用户

回答已采纳

发布于 2020-04-22 09:33:31

在调用call函数时,需要将函数f作为参数传递。但是,c++隐式地将参数转换为指向函数的指针。因此,在构造类型别名时,模板参数实际上是int(*)(int,float),而不是int(int,float)。由于这不符合部分专门化模板的要求,编译器会尝试从makeTupleOfParams的非专门化模板构造类型别名。然而,非特定模板不包含类型别名"type",这会导致编译错误。

要解决此问题,请将部分专门化的模板修改为:

代码语言:javascript
运行
复制
template<typename Return, typename... Params>
struct makeTupleOfParams<Return(*)(Params...)> //pointer-to-function specialisation
{
    using type = std::tuple<Params...>;
};

另一种解决方案是使用type_traits删除call函数中的指针特性,如下所示:

代码语言:javascript
运行
复制
#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)

票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61355549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档