-1

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

我需要知道是否有办法不提供参数计数或以 null 结束参数列表。

4

6 回答 6

3

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

如果它不会大于5,那么简单的重载可能会起作用。调用从所有其他接受少于 5 个参数的重载中接受最大参数数量的重载,或定义一个工作(内部)函数,从重载中调用它。

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

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

于 2012-08-09T06:21:43.873 回答
1

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

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

有关在每次调用中即时构建此类集合的 C++03 技术,请参阅我的其他答案;对于 C++11,如果您不需要支持 Visual C++,则可以使用花括号初始化器列表作为实际参数。

于 2012-08-09T07:20:15.630 回答
0

cstdarg是你要找的吗这是生成具有可变数量参数的函数的标准 C++ 方法。

于 2012-08-09T06:22:42.827 回答
0

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

于 2012-08-09T06:23:40.850 回答
0

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

它与 iostreams 用于operator<<.

例如

#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可变参数模板

于 2012-08-09T06:31:21.660 回答
0

你可以:

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