如何在C ++中创建一个函数来提供任意数量的参数?

时间:2014-02-23 18:09:26

标签: c++ visual-c++

我正在使用一个类来为一个选项数组调用void。这个void看起来像下面的代码,我正在尝试为charf创建一个可以提供任意数量参数的定义。如果你看下面的代码,你就会明白为什么我需要它来提供任意数量的参数。

void Player::drawOptions()
{
    u32 _q;
    const char *buffer;
    char *_1 = optBuf[0], *_2 = optBuf[1], *_3 = optBuf[2], *_4 = optBuf[3], *_5 =     optBuf[4], *_6 = optBuf[5], *_7 = optBuf[6], *_8 = optBuf[7], *_9 = optBuf[8], *_10 =     optBuf[9], *_11 = optBuf[10], *_12 = optBuf[11], *_13 = optBuf[12], *_14 = optBuf[13], *_15     = optBuf[14], *_16 = optBuf[15], *_17 = optBuf[16], *_18 = optBuf[17];
    for(_q = 0; _q<17; _q++)
    switch(_q)
    {
    case 1:buffer = charf("&s", _1);break;
        case 2:buffer = charf("%s\n%s", _1, _2);break;
        case 3:buffer = charf("%s\n%s\n%s", _1, _2, _3);break;
        case 4:buffer = charf("%s\n%s\n%s\n%s", _1, _2, _3, _4);break;
        case 5:buffer = charf("%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4, _5);break;
        case 6:buffer = charf("%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4, _5,     _6);break;
        case 7:buffer = charf("%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4, _5, _6,     _7);break;
        case 8:buffer = charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4, _5,     _6, _7, _8);break;
        case 9:buffer = charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4,     _5, _6, _7, _8, _9);break;
        case 10:buffer = charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2,     _3, _4, _5, _6, _7, _8, _9, _10);break;
        case 11:buffer = charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1,     _2, _3, _4, _5, _6, _7, _8, _9, _10, _11);break;
        case 12:buffer = charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s",     _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12);break;
        case 13:buffer =     charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4, _5, _6, _7, _8,     _9, _10, _11, _12, _13);break;
        case 14:buffer =     charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4, _5, _6, _7,     _8, _9, _10, _11, _12, _13, _14);break;
        case 15:buffer =     charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4, _5, _6,     _7, _8, _9, _10, _11, _12, _13, _14, _15);break;
        case 16:buffer =     charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4, _5,     _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16);break;
        case 17:buffer =     charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3, _4,     _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17);break;
        case 18:buffer =     charf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", _1, _2, _3,     _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18);break;
    }
    menu.max = option;
    _q = 0;
    elems[OPTIONS]->elem.text = LocalizedString(buffer),
    clearOptions();
}

我知道这格式很糟糕,但我粘贴了它在这里说的类型代码,它仍然这样做。无论如何,我知道我需要使用类似的东西:

const char* charf(const char* optName, const char* optNum)

但是我怎么做才能使optNum用于1到18个参数?

3 个答案:

答案 0 :(得分:0)

您可以使用c ++ 11可变参数模板键入charf函数,如下所示(来自http://en.cppreference.com/w/cpp/language/parameter_pack):

const char* charf(const char* optName) 
{
  //zero argument
}

template<typename T, typename... Targs>
const char* charf(const char* optName, T value, Targs... Fargs)) // recursive variadic function
{
  //handle value ...
  //charf(optName+1, Fargs...); // recursive call
}

请参阅http://en.cppreference.com/w/cpp/language/parameter_pack,了解使用此技术实施printf的示例。

答案 1 :(得分:0)

一个简单的解决方案,无需深入研究可变参数模板:

#include<cstdio>

using namespace std;

void charf(char* args[], int len){
    for (int i = 0; i < len; i++){
        printf("%s\n", args[i]);
    }
}

int main(void){
    char* foo[]{ "hello", "my", "name", "is", "slim", "shady" };
    int size = 6;
    charf(foo, size);

    system("pause");
    return 0;
}

答案 2 :(得分:0)

鉴于(至少显然)你的所有论点属于同一类型,我想我会选择一种......中间线,可以这么说。可变参数模板易于使用,但相对难以实现。数组很容易实现,但比较难以正确使用。

幸运的是,std::initializer_list易于使用易于实施:

std::string charf(std::initializer_list<std::string> const &list) {
    std::ostringstream buffer;
    std::copy(list.begin(), list.end(),
        infix_ostream_iterator<std::string>(buffer, "\n"));
    return buffer.str();
}

您可以在a question on CodeReview.SE中找到infix_ostream_iterator

使用看起来像:

std::string result = charf({ "1", "2", "3", "4", "5", "6" });

如果你真的不喜欢parens中的大括号,你也可以把它写成一个小类,如下所示:

class charf {
    std::ostringstream buffer;
public:
    charf(std::initializer_list<std::string> const &list) {
        std::copy(list.begin(), list.end(),
            infix_ostream_iterator<std::string>(buffer, "\n"));
    }
    operator std::string() const {
        return buffer.str();
    }
};

......在这种情况下,使用方式如下:

std::string result = charf{ "1", "2", "3", "4", "5", "6" };

顺便说一句:在任何一种情况下,它都不会(通常)限制在18个论点中。任何给定的编译器都可能有一个限制,但在一个典型的情况下,它可能更接近数百个参数 - 足以在任何实际观点上无限制(尽管我猜这是你在选择18时所考虑的内容) )。