如何在自定义函数

时间:2017-12-07 12:23:18

标签: c++ c++builder variadic-functions

我想使用OPENARRAY(或替代方法,如果有的话)将多个占位符变量传递给我的函数。我知道它可以通过这种方式用于String::Format

UnicodeString Text1 = "abc";
int Num2 = 1;
String::Format("Some %s and %d", OPENARRAY(TVarRec, (Text1, Num2));

我想要的是使用Text1和Text2变量:

MyFunction("Some %Txt1 and %Num2", OPENARRAY(TVarRec, ("%Txt1", Text1, "%Num2", Num2));

或者也许:

MyFunction(OPENARRAY(TVarRec, ("Some %Txt1 and %Num2", "%Txt1", Text1, "%Num2", Num2));

因此它接受文本并用适当的变量内容替换占位符变量。

我不知道的是如何从MyFunction读取OPENARRAY参数内容。

所以函数看起来像:

UnicodeString MyFunction(UnicodeString Txt, ?WHAT-HERE?)
{
// read openarray here and replace vars
return StringReplace(Txt, ?WHAT-HERE?);
}

所以我不知道如何接受OPENARRAY变量。此外,如果您有一个替代解决方案以类似的方式传递占位符,变量(不使用C ++ 11),那也是受欢迎的。

1 个答案:

答案 0 :(得分:1)

将Delphi样式的Open Array传递给函数时,实际上传递了两件事:

  • 指向数组第一个元素的指针

  • 数组的最后一个元素的索引(不是数组的长度,正如您所料!)。

因此,在您的示例中,您可以声明您的函数:

UnicodeString MyFunction(UnicodeString Txt, const TVarRec *Values, const int Values_High)

然后使用普通指针算法循环遍历数组。

TVarRec可以包含许多不同的数据类型,因此您必须查看其VType字段以了解它实际引用的数据类型,然后访问相应的数据字段。有些值(整数和单个字符)直接存储在TVarRec本身中,而其他值(字符串和其他类类型)则由指针引用。

例如:

UnicodeString MyFunction(UnicodeString Txt, const TVarRec *Values, const int Values_High)
{
    if (((Values_High + 1) % 2) != 0)
        throw Exception("uneven number of values!");

    for (int index = 0; index <= Values_High; index += 2)
    {
        String OldValue, NewValue;

        switch (Values[index].VType)
        {
            case vtString:
                OldValue = * static_cast<const ShortString*>(Values[index].VString);
                break;

            case vtPChar:
                OldValue = Values[index].VPChar;
                break;

            case vtPWideChar:
                OldValue = Values[index].VPWideChar;
                break;

            case vtAnsiString:
                OldValue = * static_cast<const AnsiString*>(Values[index].VAnsiString);
                break;

            case vtWideString:
                OldValue = * static_cast<const WideString*>(Values[index].VWideString);
                break;

            case vtUnicodeString:
                OldValue = * static_cast<const UnicodeString*>(Values[index].VUnicodeString);
                break;

            default:
                throw Exception("illegal value type at index %d!", ARRAYOFCONST(( index )) );
        }

        switch (Values[index+1].VType)
        {
            case vtInteger:
                NewValue = Values[index+1].VInteger;
                break;

            case vtBoolean:
                NewValue = Values[index+1].VBoolean;
                break;

            case vtChar:
                NewValue = Values[index+1].VChar;
                break;

            case vtExtended:
                NewValue = * static_cast<const Extended*>(Values[index+1].VExtended);
                break;

            case vtString:
                NewValue = * static_cast<const ShortString*>(Values[index+1].VString);
                break;

            case vtPChar:
                NewValue = Values[index+1].VPChar;
                break;

            case vtWideChar:
                NewValue = Values[index+1].VWideChar;
                break;

            case vtPWideChar:
                NewValue = Values[index+1].VPWideChar;
                break;

            case vtAnsiString:
                NewValue = * static_cast<const AnsiString*>(Values[index+1].VAnsiString);
                break;

            case vtCurrency:
                NewValue = * static_cast<const Currency*>(Values[index+1].VCurrency);
                break;

            case vtVariant:
                NewValue = * static_cast<const Variant*>(Values[index+1].VVariant);
                break;

            case vtWideString:
                NewValue = * static_cast<const WideString*>(Values[index+1].VWideString);
                break;

            case vtInt64:
                NewValue = * static_cast<const __int64*>(Values[index+1].VInt64);
                break;

            case vtUnicodeString:
                NewValue = * static_cast<const UnicodeString*>(Values[index+1].VUnicodeString);
                break;

            default:
                throw Exception("illegal value type at index %d!", ARRAYOFCONST(( index )) );
        }

        Txt = StringReplace(Txt, OldValue, NewValue, TReplaceFlags() << rfReplaceAll);
    }

    return Txt;
}

MyFunction("Some %Txt1 and %Num2", OPENARRAY(TVarRec, ("%Txt1", Text1, "%Num2", Num2)) );

在旁注中,当函数采用开放的TVarRec值数组时,您应该直接使用ARRAYOFCONST()宏而不是OPENARRAY()宏,例如:

String::Format("Some %s and %d", ARRAYOFCONST(( Text1, Num2 )) );

MyFunction("Some %Txt1 and %Num2", ARRAYOFCONST(( "%Txt1", Text1, "%Num2", Num2 )) );