[英]stuck with C++ metaprogramming
我正在嘗試通過一本名為Practical C++ 元編程的書進入 TMP,但我一直在嘗試推導出第一個示例...
我的目標是制作一個模板化的 function call
,調用一個帶有多個不相關類型參數的 function,然后返回帶有參數的 function 的計算。
問題的根源似乎是我無法使用適當的參數類型實例化一個結構( makeTupleOfParams
的良好專業化),這將允許我在我的代碼中定義輸入 function 參數的類型tupleOfParamTypes_t
。
我不明白為什么會出現這個問題,因為構建 output 中的 Function 簽名似乎模棱兩可,足以識別 arguments 的類型與 Ar 專業化<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);
}
以及構建 output:
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
function 時,您將 function 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
function 中的指針特征,如下所示:
#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)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.