gpt4 book ai didi

c++ - 处理重复 Prolog/Body/Epilog 模式的建议方法

转载 作者:太空宇宙 更新时间:2023-11-04 11:49:50 26 4
gpt4 key购买 nike

我有一个场景,我有很多具有以下模式的函数

RETURN_TYPE FOO(
TYPE PARM1,
TYPE PARM2)
{
PROLOG(PARM1, PARM2);
//FOO_BODY
EPILOG(PARM1, PARM2);
}

考虑遵循上述模式的示例函数

SQLRETURN SQLGetInfo(
SQLHDBC ConnectionHandle,
SQLUSMALLINT InfoType,
SQLPOINTER InfoValuePtr,
SQLSMALLINT BufferLength,
SQLSMALLINT * StringLengthPtr)
{
// ******** Prolog(InfoValuePtr, BufferLength) *************
CComSafeArray<BYTE> _InfoValuePtr(BufferLength);
LPBYTE pData;
// **********************************************************
SQLRETURN rc = p->SQLGetInfo(
reinterpret_cast<PSSQLHSTMT>(ConnectionHandle),
InfoType,
_InfoValuePtr,
BufferLength,
StringLengthPtr);
// ******** Epilog(InfoValuePtr) ******************************
::SafeArrayAccessData(_InfoValuePtr, reinterpret_cast<void **>(&pData));
memcpy_s(InfoValuePtr, BufferLength, pData, _InfoValuePtr.GetCount());
::SafeArrayUnaccessData(_InfoValuePtr);
return rc;
// *************************************************************
}

我的困境是,我对一次又一次地重复相同的代码模式感到有点不自在,这在开发过程中很容易出错并且代码膨胀。即使在明天,改变某些东西也意味着一丝不苟地改变每一个发生的事情,使其与变化保持一致。

处理模式的建议方法/最佳实践是什么? 模板

注意我们仍然没有使用 boost 并且添加 boost 只是为了解决这个问题在这里可能不是一个选项

最佳答案

@Abhijit:我自己的直觉也倾向于模板。但是,上面的示例看起来并不像上面给出的简化模型。如果你确实有大量的函数除了一些中间部分外看起来都一样,那么模板可以清理它。让你的模板参数成为一个函数指针,指向一个 Hook 到 prolog 和 epilog 的函数。这几乎是柯里化(Currying)的一种变体,但不完全是。

在不完全理解您上面的示例的情况下,以下是您如何将其转换为使用模板的草图。由于示例的主体只是一个函数调用,因此这种转换并没有真正展示模式的强大功能。但是,它应该有希望给出一个想法。

// Define the "body function" in a typedef, for sanity's sake
typedef SQLRETURN
(*SQLGetInfoFunc)(
PSSQLHSTMT,
SQLUSMALLINT,
CComSafeArray<BYTE>,
SQLSMALLINT,
SQLSMALLINT*
);

// Templated version of SQLGetInfo
template <SQLGetInfoFunc *F>
SQLRETURN SQLGetInfo(
SQLHDBC ConnectionHandle,
SQLUSMALLINT InfoType,
SQLPOINTER InfoValuePtr,
SQLSMALLINT BufferLength,
SQLSMALLINT * StringLengthPtr)
{
// ******** Prolog(InfoValuePtr, BufferLength) *************
CComSafeArray<BYTE> _InfoValuePtr(BufferLength);
LPBYTE pData;
// **********************************************************
SQLRETURN rc = F(
reinterpret_cast<PSSQLHSTMT>(ConnectionHandle),
InfoType,
_InfoValuePtr,
BufferLength,
StringLengthPtr);
// ******** Epilog(InfoValuePtr) ******************************
::SafeArrayAccessData(_InfoValuePtr, reinterpret_cast<void **>(&pData));
memcpy_s(InfoValuePtr, BufferLength, pData, _InfoValuePtr.GetCount());
::SafeArrayUnaccessData(_InfoValuePtr);
return rc;
// *************************************************************
}

在此示例中,F 是您将作为模板参数提供的函数指针。也就是说,我注意到您的原始示例使用了 p->SQLGetInfo,但我没有看到 p 的定义位置。

为了提供显示基本模式的完整示例,请考虑以下代码:

#include <iostream>

typedef int (*fxn)(int);

inline int fred(int x)
{
return x + 100;
}

inline int barney(int x)
{
return x + 200;
}


template <fxn F>
void apply_to_array(int *array, int len)
{
for (int i = 0; i < len; i++)
array[i] = F(array[i]);
}

using namespace std;

void print_array(int *array, int len)
{
for (int i = 0; i < len; i++)
cout << " " << array[i];

cout << endl;
}


int af[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int ab[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

int main(void)
{
cout << "Before: af = ";
print_array(af, 10);

apply_to_array<fred>(af, 10);

cout << "After apply_to_array<fred>(af): af = ";
print_array(af, 10);

cout << "Before: ab = ";
print_array(ab, 10);

apply_to_array<barney>(ab, 10);

cout << "After apply_to_array<barney>(ab): ab = ";
print_array(ab, 10);

return 0;
}

输出如下:

Before: af =  1 2 3 4 5 6 7 8 9 10
After apply_to_array<fred>(af): af = 101 102 103 104 105 106 107 108 109 110
Before: ab = 1 2 3 4 5 6 7 8 9 10
After apply_to_array<barney>(ab): ab = 201 202 203 204 205 206 207 208 209 210

关于c++ - 处理重复 Prolog/Body/Epilog 模式的建议方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18809018/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com