我怎么能写一个函数,接受可变数量的参数?这可能吗?怎么可能?
当前回答
现在有可能……使用boost任意和模板 在这种情况下,参数类型可以混合
#include <boost/any.hpp>
#include <iostream>
#include <vector>
using boost::any_cast;
template <typename T, typename... Types>
void Alert(T var1,Types... var2)
{
std::vector<boost::any> a( {var1,var2...});
for (int i = 0; i < a.size();i++)
{
if (a[i].type() == typeid(int))
{
std::cout << "int " << boost::any_cast<int> (a[i]) << std::endl;
}
if (a[i].type() == typeid(double))
{
std::cout << "double " << boost::any_cast<double> (a[i]) << std::endl;
}
if (a[i].type() == typeid(const char*))
{
std::cout << "char* " << boost::any_cast<const char*> (a[i]) <<std::endl;
}
// etc
}
}
void main()
{
Alert("something",0,0,0.3);
}
其他回答
你可能不应该这样做,你可以用一种更安全、更简单的方式做你想做的事情。从技术上讲,要在C语言中使用可变数量的参数,需要包含stdarg.h。由此,您将获得va_list类型以及对其进行操作的三个函数va_start()、va_arg()和va_end()。
#include<stdarg.h>
int maxof(int n_args, ...)
{
va_list ap;
va_start(ap, n_args);
int max = va_arg(ap, int);
for(int i = 2; i <= n_args; i++) {
int a = va_arg(ap, int);
if(a > max) max = a;
}
va_end(ap);
return max;
}
要我说,这真是一团糟。它看起来很糟糕,不安全,而且充满了与你在概念上试图实现的目标无关的技术细节。相反,可以考虑使用重载或继承/多态性、构建器模式(如流中的操作符<<())或默认参数等。这些都是更安全的:编译器会更多地了解你要做什么,这样就有更多的机会在你断腿之前阻止你。
除了可变参数或重载,你可以考虑将参数聚合在std::vector或其他容器中(例如std::map)。就像这样:
template <typename T> void f(std::vector<T> const&);
std::vector<int> my_args;
my_args.push_back(1);
my_args.push_back(2);
f(my_args);
通过这种方式,您将获得类型安全,并且这些可变参数的逻辑含义将是显而易见的。
当然,这种方法可能会有性能问题,但您不必担心,除非您确定无法为此付出代价。它是c++的一种“Pythonic”方法…
唯一的方法是使用C样式变量参数,如下所述。请注意,这不是一个推荐的实践,因为它不类型安全且容易出错。
使用可变模板,示例重现console.log,如JavaScript所示:
Console console;
console.log("bunch", "of", "arguments");
console.warn("or some numbers:", 1, 2, 3);
console.error("just a prank", "bro");
文件名,例如js_console.h:
#include <iostream>
#include <utility>
class Console {
protected:
template <typename T>
void log_argument(T t) {
std::cout << t << " ";
}
public:
template <typename... Args>
void log(Args&&... args) {
int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
cout << endl;
}
template <typename... Args>
void warn(Args&&... args) {
cout << "WARNING: ";
int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
cout << endl;
}
template <typename... Args>
void error(Args&&... args) {
cout << "ERROR: ";
int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
cout << endl;
}
};
现在有可能……使用boost任意和模板 在这种情况下,参数类型可以混合
#include <boost/any.hpp>
#include <iostream>
#include <vector>
using boost::any_cast;
template <typename T, typename... Types>
void Alert(T var1,Types... var2)
{
std::vector<boost::any> a( {var1,var2...});
for (int i = 0; i < a.size();i++)
{
if (a[i].type() == typeid(int))
{
std::cout << "int " << boost::any_cast<int> (a[i]) << std::endl;
}
if (a[i].type() == typeid(double))
{
std::cout << "double " << boost::any_cast<double> (a[i]) << std::endl;
}
if (a[i].type() == typeid(const char*))
{
std::cout << "char* " << boost::any_cast<const char*> (a[i]) <<std::endl;
}
// etc
}
}
void main()
{
Alert("something",0,0,0.3);
}