3

存在三种类型的序列,例如std::string, int, int。C++ 中是否有模板允许函数将无限数量的序列作为参数?

Function("Peter", 27, 89,
         "Max",   25, 72,
         "Frank", 32, 94,
         "David", 31, 98);
4

3 回答 3

7

问题是“你和那个序列有什么关系”。

可以采用任意的参数序列并将它们 3 x 3 分配给仅采用 3 的函数:

void Function(string n, int a, int b) 
{ /* base action here */ }

template<class... Others>
void Function(string n1, int a1, int b1, const Others&... t)
{
    Function(n1, a1, b1);
    Function(t...);
}

只有当参数类型与基本函数重复匹配时,它才会编译。

于 2013-06-15T13:05:55.187 回答
5

以下是我想到的几种方法:

可变参数模板: C++11

(由 Emilio Garavaglia 的回答所涵盖,所以我不会重复)

initializer_list年代: C++11

(类似于 ChriZzZ 的回答,但std::initializer_list直接使用)

struct Sequence {
    std::string name;
    int numberA;
    int numberB;
};

#include <initializer_list>
void Function(std::initializer_list<Sequence> aLotOfData)
{
    for(const Sequence& s : aLotOfData)
    {
        // do operations on s.name, s.numberA, s.numberB
    }
}
//usage example
Function({ {"Peter", 27, 89}, {"Max", 25, 72} });

(这里结束了简单的解决方案列表)

最多 N 个参数的重载函数:

void Function(string n1, int a1, int b1) { /* ??? */ }
void Function(string n1, int a1, int b1, string n2, int a2, int b2) { /* ??? */ }
void Function(string n1, int a1, int b1, string n2, int a2, int b2, string n3, int a3, int b3) { /* ??? */ }
//usage example
Function("Peter", 27, 89, "Max", 25, 72);

实际上它并没有那么糟糕 - 如果你可以假设没有人会用超过 N 个参数调用它(琐事:C 标准建议 C 编译器支持 128 个参数的最小限制)并且你不会手动编码(使用预处理器,但不一定是 C 预处理器 - 因为它是预处理的最低公分母。Boost 使用自己的预处理器处理非 C++11 代码中的可变参数。或者您可以使用 C++ 程序生成 C++ 代码并将输出文件包含在源代码中代码 - 现在是 C++ 元编程 ;-) )。

数组初始化并传递给函数(或者,使用指针和sizeof):

struct Sequence
{
    std::string name;
    int numberA;
    int numberB;
};

#include <cstddef>
template<std::size_t N>
void Function(Sequence (&data)[N])
{
    for(std::size_t i = 0; i < N; ++i)
    {
        // do operations on data[i].name, data[i].numberA, data[i].numberB
    }
}
//usage example
Sequence args[] = { {"Peter", 27, 89}, {"Max", 25, 72} };
Function(args);

可以在 C 中使用类似的解决方案。(在 C99 中,您甚至可以使用复合文字来提供内联参数)

方法/函数/运算符链接

struct Function
{
    const Function& operator()(string name, int na, int nb) const
    {
        // do operations to name, na, nb
        return *this;
    }

    void operator() const
    {
        //base case
        //optional here - return values
    }
};
//usage example
Function()("Peter", 27, 89)("Max", 25, 72)();

链接用于 C++ iostreams 和 Boost.Assign。在这个实现中,调用者可能忘记包含最后的括号,函数不会做最后的事情——肯定会有更好的实现。

C 可变参数

#include <cstdarg>
void Function(std::size_t count, ...)
{
    va_list ap;
    va_start(ap, count);
    for(std::size_t i = 0; i < count; ++i)
    {
        string name = va_arg(ap, const char*);
        int na = va_arg(ap, int);
        int nb = va_arg(ap, int);
        // do operations on name, na, nb
    }
    va_end(ap);
}
//usage example (the first argument refers to count of arguments - it has to match)
Function(2, "Peter", 27, 89, "Max", 25, 72);

非常非常糟糕的解决方案。我们不得不丢弃std::string作为参数并将其替换const char*为非 POD 不能传递给 varargs 函数(或者我们可以传递指向 的指针std::string)。请注意,此处的任何错误都会导致未定义的行为。编译器不会检查 args 的类型,并且会盲目地相信我们传递了正确类型的参数。

于 2013-06-16T02:17:26.447 回答
1

只需使用结构和某种容器。

void Function(std::vector<Sequence> aLotOfData);


struct Sequence {
    std::string name;
    int numberA;
    int numberB;
};
于 2013-06-15T13:03:50.290 回答