变量参数

时间:2012-08-09 06:19:45

标签: c++ c

是否有一种非增强方式来创建具有可变参数的函数?我知道参数类型 参数个数,它们通常小于5,所有相同的类型

我需要知道是否存在不提供参数计数或以null结束参数列表的方法。

6 个答案:

答案 0 :(得分:3)

  

我知道参数类型,它们通常小于5。

如果它不会大于5,那么简单的重载可以完成工作。调用重载,该重载接受来自接受少于5个参数的所有其他重载的maximam数量的参数,或者定义一个worker(内部)函数,从重载中调用它。

如果可能,您可以对某些参数使用默认值,如果这有助于减少重载函数的数量。

在C ++ 11中,您可以使用variadic-template

答案 1 :(得分:1)

对于所有相同类型的最多5个参数,简单的重载可以解决问题。

为了更加通用,支持相同类型的任意数量的参数,只需传递一个集合,例如std::vector

对于在每次调用中动态构建此类集合的C ++ 03技术,请参阅my other answer;对于C ++ 11,如果您不需要支持Visual C ++,则可以使用花括号初始化列表作为实际参数。

答案 2 :(得分:0)

cstdarg您要找的是什么?这是生成具有可变数量参数的函数的标准C ++方法。

答案 3 :(得分:0)

您应该能够使用va_list来传递变量参数。

答案 4 :(得分:0)

作为一般的C ++ 03解决方案,您可以提供一个setter,它返回对它所调用的对象的引用,以便可以再次调用它。然后再次。等等,称为链接

这与iostream用于operator<<的方案相同。

E.g。

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

void foo( char const s[] )
{
    cout << s << endl;
}

class StringBuilder
{
private:
    string      s_;

    template< class Type >
    string fastStringFrom( Type const& v )
    {
        stringstream stream;
        stream << v;
        return stream.str();
    }

    char const* fastStringFrom( char const* s )
    {
        return s;
    }

    string const& fastStringFrom( string const& s )
    {
        return s;
    }

public:
    template< class Type >
    StringBuilder& operator<<( Type const& v )
    {
        s_ += fastStringFrom( v );
        return *this;                   // Supports chaining.
    }

    operator string const& () const { return s_; }
    operator char const* () const { return s_.c_str(); }
};

int main()
{
    typedef StringBuilder S;

    foo( S() << "6*7 = " << 6*7 << "." );   // Any number of arguments.
}

不是将参数值转换为文本,而是根据需要做任何事情。例如,使用一组固定的可能类型,您可以将参数存储在集合中。

如果您不需要支持Visual C ++编译器,那么您也可以使用C ++ 11 可变参数模板

答案 5 :(得分:0)

你可以:

  • 如果您使用的是C ++ 11,则可以使用可变参数模板,否则......
  • 提供重载
  • 使用默认为某些标记值的参数,您可以识别ala f(const T& v1 = missing, const T& v2 = missing, ...) { if (v5 != missing) ...
  • 创建一个简单的帮助器模板,可以选择从数据类型构造,并有一个bool来跟踪它是否是
    • 您可能需要支持没有默认构造函数的类型,方法是使用new / delete(简单且安全但速度慢)或使用对齐缓冲区放置new,手动销毁等等。(繁琐且容易出错)但更快)
  • 一些编译器具有可变宏支持
  • 如果您准备稍微更改调用语法,可以使用任意数量的东西:
    • 接受一个向量(如果类型不同,使用union或variant)
    • 接受一个数组(可能使用template <size_t N> void f(T (&data)[N]) { ... }技巧让编译器自动为你提供数组大小)
    • 使用operator,operator<<
    • 等运算符可以提供额外值的某种lhs对象