C ++中可变的用户定义参数列表?

时间:2011-04-08 18:54:06

标签: c++

我正在寻找一种创建用户多参数接收函数的简单方法,

这是一些伪代码

#include <iostream>

struct A {
   int m_num;
};

void function(A* a, ...)
{
    /* Pseudo-Code here */
    for each parameter do 
        print a->m_num
    end
}

int main()
{
   A *a = new A();
   A *b = new A();
   A *c = new A();

   a->m_num = 1;
   b->m_num = 10;
   c->m_num = 100;

   function(a,b,c);

   // delete everything

   return 0;
}

我不能在这里使用boost,所以如果可以使用标准C ++(允许STL),那就太棒了。

编辑:函数参数是异构的

5 个答案:

答案 0 :(得分:3)

旧派平原C可变参数:

#include <cstdio>
#include <stdarg.h>

struct A {
    A () : m_num (0) {}
    A (int v) : m_num (v) {}
    int m_num;
};

void function (A *a, ...)
{
    va_list ap;
    A *p = a;
    va_start (ap, a);
    while (p != NULL)
    {
        printf ("%d\n", p->m_num);
        p = va_arg (ap, A*);
    }
    va_end (ap);
}

int main()
{
    A a (1), b (10), c (100);
    function (&a, &b, &c, NULL);
}

如果参数属于同一类型(在您的情况下),则为另一种解决方案:

#include <cstdio>

struct A {
    A () : m_num (0) {}
    A (int v) : m_num (v) {}
    int m_num;
};

void function (A *p, A *endp)
{
    while (p != endp)
    {
        printf ("%d\n", p->m_num);
        ++p;
    }
}

int main()
{
    A a[3];
    a[0].m_num = 1;
    a[1].m_num = 10;
    a[2].m_num = 100;
    function (a, a + sizeof (a) / sizeof(a[0]));
}

甚至更多C ++风格,带迭代器:

#include <cstdio>
#include <vector>
#include <list>

struct A {
    A () : m_num (0) {}
    A (int v) : m_num (v) {}
    int m_num;
};

template <typename T>
void function (T p, T endp)
{
    while (p != endp)
    {
        printf ("%d\n", p->m_num);
        ++p;
    }
}

int main()
{
    A a[3];
    a[0].m_num = 1;
    a[1].m_num = 10;
    a[2].m_num = 100;
    function (a, a + sizeof (a) / sizeof(a[0]));

    std::vector<A> av (3);
    av[0].m_num = 1;
    av[1].m_num = 10;
    av[2].m_num = 100;
    function (av.begin (), av.end ());

    std::list<A> al;
    al.push_back (A (1));
    al.push_back (A (10));
    al.push_back (A (100));
    function (al.begin (), al.end ());
}

答案 1 :(得分:1)

最直接的方法是将参数放入std::vector。如果它们是非同类的,您可以使用boost::anyboost::variant的矢量。

或者像流一样设计你的界面,并使用类似操作符/函数的插入,一次操作一个参数。

看起来像这样,交替使用朋友自由功能。

struct A
{
   int m_num;
};

struct printer
{
function& operator<<(A* a)
{
    /* Pseudo-Code here */
    print a->m_num

    return *this;
}
};

int main()
{
   A *a = new A();
   A *b = new A();
   A *c = new A();

   a->m_num = 1;
   b->m_num = 10;
   c->m_num = 100;

   printer function;
   function << a << b << c;

   // delete everything

   return 0;
}

答案 2 :(得分:0)

如果进入函数的每个参数都是A,我会使用A的数组来完成,如:

int main() {
  A *abc[3];

  for (int i=0;i<3;i++)
    abc[i]=new A();

  abc[0]->m_num=1;
  abc[1]->m_num=10;
  abc[2]->m_num=100;

  function(abc,3);
}

void function(A *vals[],int count) {
  for (int i=0;i<count;i++)
    print vals[i]->m_num;
}

答案 3 :(得分:0)

如果最近有一个编译器可以随std::tuple<>std::tr1::tuple<>一起提供,您可以执行以下操作:

#include <cstddef>
#include <tuple>
#include <iostream>

struct A
{
    int m_num;
};

template<typename T>
class function_impl
{
    template<std::size_t N>
    static void impl(T const& tup)
    {
        std::cout << std::get<N>(tup)->m_num << '\n';
    }

    template<std::size_t N>
    struct recurse_helper
    {
        static void invoke(T const& tup)
        {
            function_impl<T>::template impl<N>(tup);
            recurse_helper<N + 1u>::invoke(tup);
        }
    };

    template<>
    struct recurse_helper<std::tuple_size<T>::value>
    {
        static void invoke(T const&) { }
    };

public:
    static void invoke(T const& tup)
    {
        recurse_helper<0u>::invoke(tup);
    }
};

template<typename T>
void function(T const& tup)
{
    function_impl<T>::invoke(tup);
}

int main()
{
    A* a = new A();
    a->m_num = 1;

    A* b = new A();
    b->m_num = 10;

    A* c = new A();
    c->m_num = 100;

    function(std::tie(a, b, c));

    delete c;
    delete b;
    delete a;
}

请注意,function实际上采用单个参数,tuple<>,而不是多个参数。但是,与任何基于varargs的解决方案不同,这是完全类型安全的。

另请注意,如果您可以使用Boost,那么此处的实施将会更加简单。Fusion ...

答案 4 :(得分:0)

作为补充。

在C ++ 0x中,你可以使用variadic-template来递归地实现你的函数

// Just to make the compiler happy.
template <typename T>
void function(T a) = delete;

// Base case
template <>
void function(A* a) {
    printf("%d\n", a->m_num);
}

// Recursion
template <typename T, typename... Args>
void function(T a, Args... args) {
    function(a);
    function(args...);
}

但如果它接受 N 参数,这将生成 N 函数。或者,您可以使用initializer_list

void function(std::initializer_list<A*> args) {
    for (auto cit = args.begin(); cit != args.end(); ++ cit)
        printf("%d\n", (*cit)->m_num);
}

但您需要将function称为

function({a,b,c});
//       ^     ^