【发布时间】:2018-03-12 05:29:24
【问题描述】:
我在模板的帮助下以一种特定的方式调用 API,但我在传递一个常量参数时留下了一个问题。
我对 int bound 的尝试:
template <typename F, typename ...Ts>
static int f3(int bound, CString file, int line, CString Caller,
CString f_name, F f, Ts&& ...ts) {
int err = fn(bound, file, line, Caller, f_name,
f, std::tuple<Ts...>(ts...), seq3<bound>{}, // error C2975
seq1<sizeof...(Ts)>{});
return err;
}
主要:
int const bound;
bound = 4;
err = fn(bound, api(GetModuleFileName), rval, nullptr, path, MAX_PATH, L"EXE-path");
compiler error C2975: 'N': invalid template argument for 'seq3', expected compile-time constant expression
如何解决这个问题?
我现在的解决方法:
err = f3(api(GetModuleFileName), rval, nullptr, path, MAX_PATH, L"EXE-path");
f3 是具有 3 个参数的 API 的特化,因为到目前为止我无法传入上限(在本例中为 4)来生成序列:。 需要此序列来调用具有 3 个参数的 API,其中元组从 f3() 中的参数 rval 开始。
背景:
api 是一个#define
f3 调用 API。
f3在sequence/tupel的0位置处理API的返回值。
f3 使用所有参数调用另一个可变参数函数来记录调试信息。
两个函数调用的一个元组和两个序列。
问题:
我想传递一个参数来控制不是由 tupel-size 而是由 API 函数签名给出的序列的上限。
我只想要一个 fn() 用于所有 API,而不是 f0()、f1()、f2()、f3() ..... 用于具有 0、1、2、3 ... 参数的 API。
我想要这样的东西:
err = fn(seq3, api(GetModuleFileName), rval, nullptr, path, MAX_PATH, L"EXE-path")
这是我的工作代码:
#include <windows.h>
#include <atlstr.h>
#include <tuple>
#include <utility>
template <int ... Ns> struct seq_3 {};
template <int ... Ns> struct seq3_n {};
template <int I, int ... Ns> struct seq3_n<I, Ns...>{
using type = typename seq3_n<I - 1, I - 1, Ns...>::type;};
template <int ... Ns> struct seq3_n<1, Ns...>{
// skip first argument : rval, because it doesn't fit to API,
// but needed for calling other function
using type = seq_3<Ns...>; };
template <int N>
using seq3 = typename seq3_n<N>::type;
template <int ... Ms> struct seq_1 {};
template <int ... Ms> struct seq1_n {};
template <int J, int ... Ms> struct seq1_n<J, Ms...>{
using type = typename seq1_n<J - 1, J - 1, Ms...>::type; };
template <int ... Ms> struct seq1_n<0, Ms...> {
using type = seq_1<Ms...>; };
template <int M>
using seq1 = typename seq1_n<M>::type;
template <typename F, typename TUP, int ... INDICES3, int ... INDICES1>
static int fn(CString file, int line, CString Caller, CString f_name,
F f, TUP tup, seq_3<INDICES3...>, seq_1<INDICES1...>) {
int err = 0;
// handling of rval = first element of tuple
std::get<0>(tup) = f(std::get<INDICES3>(tup) ...); // calling API
err = GetLastError();
/* calling next function (variadic too) with same tupel, but other sequence
myOpenDebugOutputString(project, file, line, Caller, f_name, std::get<INDICES1>(tup) ..., "stop");
*/
return err; }
template <typename F, typename ...Ts>
static int f3(CString file, int line, CString Caller, CString f_name,
F f, Ts&& ...ts) {
int err = fn(file, line, Caller, f_name,
f, std::tuple<Ts...>(ts...), seq3<4>{}, // sequence fixed by f3
seq1<sizeof...(Ts)>{}); // 3 arguments api + skip 1 rval = 4
return err; // given by signature of API
}
int main() {
// for calling simple API GetModulFileName with 3 arguments
// returns len(path)
wchar_t path[MAX_PATH];
DWORD rval = 0;
int err = 0;
rval = GetModuleFileName( nullptr, path, MAX_PATH);
err = GetLastError();
#define api(a) __FILE__, __LINE__, __func__, L#a, a
// L#a becomes L"GetModuleFileName"
err = f3(api(GetModuleFileName), rval, nullptr, path, MAX_PATH, L"EXE-path");
return 0; }
提前致谢。
附: 我正在使用 Microsoft Visual Studio 2015
更新:
我尝试遵循 Richard Hodges 解决方案的模板 api_call。
std::tuple<GivenArgs...> tup(args...);
// OK, but only for an api with 3 arguments
callsite.function(std::get<0>(tup), std::get<1>(tup), std::get<2>(tup));
// compiler error too many arguments
callsite.function(std::forward<GivenArgs>(args)..., seq1<callsite.nofArgs()>{});
// compiler error too few arguments
callsite.function(tup, seq1<callsite.nofArgs()>{});
备注:
seq1 = seq_1
callsite.nofArg() = 3
如何获得正确数量的参数?
【问题讨论】:
-
你到底想做什么?记录对 API 的调用,包括有关调用站点的信息?
-
^那个。我也不明白这个问题,但如果你有任何错误信息,edit他们。
-
是的,我正在尝试以格式化的方式记录呼叫站点信息和许多其他变量。
-
完成:在底部的错误消息中进行了编辑。
标签: c++ templates sequences variadic