我怎么能写一个函数,接受可变数量的参数?这可能吗?怎么可能?
当前回答
c++ 17解决方案:完全类型安全+良好的调用语法
由于在c++ 11中引入了变进模板,在c++ 17中引入了fold表达式,因此可以在调用端定义一个模板函数,它可以像一个变进函数一样被调用,但优点是:
强类型安全; 在不使用参数数量的运行时信息或不使用“stop”参数的情况下工作。
下面是一个混合参数类型的例子
template<class... Args>
void print(Args... args)
{
(std::cout << ... << args) << "\n";
}
print(1, ':', " Hello", ',', " ", "World!");
另一个对所有参数强制类型匹配:
#include <type_traits> // enable_if, conjuction
template<class Head, class... Tail>
using are_same = std::conjunction<std::is_same<Head, Tail>...>;
template<class Head, class... Tail, class = std::enable_if_t<are_same<Head, Tail...>::value, void>>
void print_same_type(Head head, Tail... tail)
{
std::cout << head;
(std::cout << ... << tail) << "\n";
}
print_same_type("2: ", "Hello, ", "World!"); // OK
print_same_type(3, ": ", "Hello, ", "World!"); // no matching function for call to 'print_same_type(int, const char [3], const char [8], const char [7])'
// print_same_type(3, ": ", "Hello, ", "World!");
^
更多信息:
可变参数模板,也称为参数包(自c++ 11起)- cppreference.com。 折叠表达式(自c++ 17开始) 查看coliru上的完整程序演示。
其他回答
在c++ 11中,有一种方法可以创建变量参数模板,从而以一种非常优雅且类型安全的方式来使用变量参数函数。Bjarne自己在c++ 11FAQ中给出了一个使用变量参数模板的printf的好例子。
就我个人而言,我认为这是如此优雅,以至于在编译器支持c++ 11变量参数模板之前,我甚至不会为c++中的变量参数函数而烦恼。
唯一的方法是使用C样式变量参数,如下所述。请注意,这不是一个推荐的实践,因为它不类型安全且容易出错。
如果所有实参都是const且类型相同,也可以使用initializer_list
除了可变参数或重载,你可以考虑将参数聚合在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++ 11
是通用的,适用于所有数据类型 类似JavaScript console.log(1,"23") 支持颜色代码的信息,警告,错误。 例子:
#pragma once
#include <iostream>
#include <string>
const std::string RED = "\e[0;91m";
const std::string BLUE = "\e[0;96m";
const std::string YELLOW = "\e[0;93m";
class Logger {
private:
enum class Severity { INFO, WARN, ERROR };
static void print_colored(const char *log, Severity severity) {
const char *color_code = nullptr;
switch (severity) {
case Severity::INFO:
color_code = BLUE.c_str();
break;
case Severity::WARN:
color_code = YELLOW.c_str();
break;
case Severity::ERROR:
color_code = RED.c_str();
break;
}
std::cout << "\033" << color_code << log << "\033[0m -- ";
}
template <class Args> static void print_args(Args args) {
std::cout << args << " ";
}
public:
template <class... Args> static void info(Args &&...args) {
print_colored("[INFO] ", Severity::INFO);
int dummy[] = {0, ((void)print_args(std::forward<Args>(args)), 0)...};
std::cout << std::endl;
}
template <class... Args> static void warn(Args &&...args) {
print_colored("[WARN] ", Severity::WARN);
int dummy[] = {0, ((void)print_args(std::forward<Args>(args)), 0)...};
std::cout << std::endl;
}
template <class... Args> static void error(Args &&...args) {
print_colored("[ERROR]", Severity::ERROR);
int dummy[] = {0, ((void)print_args(std::forward<Args>(args)), 0)...};
std::cout << std::endl;
}
};
推荐文章
- 为什么我的程序不能在Windows 7下用法语编译?
- 如何获取变量的类型?
- 什么是奇怪的重复模板模式(CRTP)?
- 连接两个向量的最佳方法是什么?
- 在c++中,是通过值传递更好,还是通过引用到const传递更好?
- 在STL中deque到底是什么?
- Windows上最好的免费c++分析器是什么?
- 如何自动转换强类型枚举为int?
- 在一个类中使用具有成员函数的泛型std::function对象
- 'for'循环中的后增量和前增量产生相同的输出
- 虚函数和纯虚函数的区别
- c++中的_tmain()和main()有什么区别?
- 内存泄漏是否正常?
- 当启用c++ 11时,std::vector性能回归
- 什么时候使用哪种指针?