템플릿을 사용하여 특정 방식으로 API를 호출하고 있으며 상수 매개 변수를 전달하는 데 한 가지 문제가 있습니다.C++ 시퀀스의 상위 범위를 가변 함수 템플릿
INT 바운드 나의 시도 : 주에서
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, 경로 MAX_PATH, L "EXE 경로");
f3은 최대 인수 (이 경우 4)를 전달할 수 없으므로 3 개의 인수가있는 API의 특수화입니다. < 1,2,3>. 이 시퀀스는 tupel이 f3()의 매개 변수 rval에서 시작하는 3 개의 인수로 API를 호출하는 데 필요합니다.
배경 :
API를 정의 #
F3는 API를 호출합니다.
f3은 시퀀스/튜플의 0 위치에서 API의 반환 값을 처리합니다.
f3은 모든 매개 변수로 디버그 정보를 기록하는 또 다른 가변 함수를 호출합니다.
두 개의 함수 호출에 대해 하나의 투플과 두 개의 시퀀스.
문제 :
나는 tupel 크기가 아니라 API 함수 서명에 의해 주어지지 시퀀스의 상한을 제어하는 매개 변수를 전달하고 싶다.
0, 1, 2, 3 ... 인수가있는 API의 경우 f0(), f1(), f2(), f3() .....이 아닌 모든 API에 대해 하나의 fn .
나는 이런 식으로 뭔가 싶어 :
ERR = FN (seq3 < 4>, API (하여 GetModuleFileName), rval에, nullptr, 경로, MAX_PATH는, L "EXE 경로")는
여기 내 작업의 코드 :
#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; }
미리 감사드립니다.
P. 나는 마이크로 소프트 비주얼 스튜디오에게 2015
업데이트를 사용하고 있습니다 : 나는 리처드 스 솔루션에서 템플릿 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 < 3> = seq_1 < 0,1,2>
callsite.nofArg() =의 정확한 수를 얻을 수있는 방법
3
논쟁?
실제로 무엇을하려고합니까? 콜 사이트에 대한 정보를 포함하여 API에 호출을 기록 하시겠습니까? –
^그. 나는이 질문을 이해하지 못한다. 그러나 만약 당신이 에러 메시지를 가지고 있다면 그것들을 [편집]한다. –
네, 포맷 된 방식으로 호출 사이트 정보와 많은 다른 변수를 기록하려고합니다. – CarpeDiemKopi