C++ 传递标准::向量<;int>;变量函数项
我使用的是GCC4.6。 假设有一个参数向量v,我必须传递给一个可变函数f(const char*format,…) 一种方法是:C++ 传递标准::向量<;int>;变量函数项,c++,gcc,arguments,stdvector,variadic-functions,C++,Gcc,Arguments,Stdvector,Variadic Functions,我使用的是GCC4.6。 假设有一个参数向量v,我必须传递给一个可变函数f(const char*format,…) 一种方法是: void VectorToVarArgs(vector<int> &v) { switch(v.size()) { case 1: f("%i", v[0]); case 2: f
void VectorToVarArgs(vector<int> &v)
{
switch(v.size())
{
case 1: f("%i", v[0]);
case 2: f("%i %i", v[0], v[1]);
case 3: f("%i %i %i", v[0], v[1], v[2]);
case 4: f("%i %i %i %i", v[0], v[1], v[2], v[3]);
// etc...
default:
break;
}
}
// where function f is
void f(const char* format, ...)
{
va_list args;
va_start (args, format);
vprintf (format, args);
va_end (args);
}
void vectorovargs(向量&v)
{
开关(v.size())
{
案例1:f(“%i”,v[0]);
案例2:f(“%i%i”,v[0],v[1]);
案例3:f(“%i%i%i”,v[0],v[1],v[2]);
案例4:f(“%i%i%i%i”,v[0],v[1],v[2],v[3]);
//等等。。。
违约:
打破
}
}
//其中函数f是
void f(常量字符*格式,…)
{
va_列表参数;
va_开始(参数,格式);
vprintf(格式,参数);
va_端(args);
}
问题当然是它不支持向量v中任意数量的项。
然而,我相信我已经理解了va_列表在原则上的工作原理,
i、 e.从堆栈中读取参数,从“…”之前最后一个命名参数的地址开始,
现在我认为应该可以将向量项值复制到内存块(例如myMemBlock)
并将其地址作为“format”后的第二个参数传递。
显然,这需要myMemBlock按照f()的预期结构,即像堆栈一样
您可以使用STL算法来打印每个向量项。在下面的“创建一个虚假的变量列表”部分。它是为Cocoa设计的,但是你可能会在网上找到一些关于GCC的东西 那么,我猜你会这样做:
#include <string>
#include <cstdio>
#include <vector>
#include <cstdarg>
using namespace std;
struct my_list {
unsigned int gp_offset;
unsigned int fp_offset;
void *overflow_arg_area;
void *reg_save_area;
};
void f(const char* format, ...) {
va_list args;
va_start (args, format);
vprintf (format, args);
va_end (args);
}
void test(const vector<int>& v) {
string fs;
for (auto i = v.cbegin(); i !=v.cend(); ++i) {
if (i != v.cbegin()) {
fs += ' ';
}
fs += "%i";
}
my_list x[1];
// initialize the element in the list in the proper way
// (however you do that for GCC)
// where you add the contents of each element in the vector
// to the list's memory
f(fs.c_str(), x);
// Clean up my_list
}
int main() {
const vector<int> x({1, 2, 3, 4, 5});
test(x);
}
#包括
#包括
#包括
#包括
使用名称空间std;
构造我的列表{
无符号整数gp_偏移量;
无符号整数fp_偏移量;
无效*溢出面积;
void*reg\u save\u区域;
};
void f(常量字符*格式,…){
va_列表参数;
va_开始(参数,格式);
vprintf(格式,参数);
va_端(args);
}
无效测试(常数向量和v){
字符串fs;
对于(自动i=v.cbegin();i!=v.cend();++i){
如果(i!=v.cbegin()){
fs+='';
}
fs+=%i;
}
我的清单x[1];
//以正确的方式初始化列表中的元素
//(不管您如何为GCC这样做)
//将每个元素的内容添加到向量中
//到列表的内存中
f(fs.c_str(),x);
//清理我的清单
}
int main(){
常数向量x({1,2,3,4,5});
试验(x);
}
但是,我完全不知道 你的反射没有处于正确的抽象层次 当您说要将向量转换为变量参数列表时,这是因为获取变量参数列表的函数做了一些您感兴趣的事情 因此,真正的问题是,我如何能做与
f
相同的事情,但从向量开始
将呼叫转发到f
可能最终开始解决方案,但这并不明显
如果只是关于打印:
void f(std::vector<int> const& vi) {
bool first = true;
for (int i: vi) {
if (first) { first = false; } else { std::cout << ' '; }
std::cout << i;
}
}
void f(标准::向量常量&vi){
bool first=true;
用于(int i:vi){
如果(first){first=false;}else{std::cout好的,这里有一个部分解!
部分,因为它不适用于真正的可变函数,
但对于那些接受一份清单作为论据的人来说。
但我认为完整的解决方案并不遥远
它基于我在这里找到的示例:
动态创建虚拟联盟列表
打造一个虚拟列表
此代码在linux和VC++2008上用gcc成功测试,
其他平台也可能得到支持,但这取决于您
对我来说,最重要的一点是va_列表基本上就是一个压缩数组,
它可以动态地填充数据,并可以传递给以下函数
vprintf、vfprintf、vsprintf,它们接受它作为参数
因此,通过分配足够的内存,可以将向量项传递给其中一个函数
用于向量项,并在调用之前复制它们
话虽如此,以下是动态分配堆栈的方法:
#include <iostream>
#include <stdio.h>
#include <stdarg.h>
#include <string>
#include <vector>
#include <alloca.h>
using namespace std;
class Format
{
typedef vector<unsigned long> ULVector;
ULVector _args;
string _format;
public:
Format(const char* format) : _format(format)
{}
Format &operator<<(int arg) {
_args.push_back((unsigned long)arg);
return *this;
}
Format &operator<<(const char* arg) {
_args.push_back((unsigned long)arg);
return *this;
}
string format() {
union {
va_list varargs;
unsigned long* packedArray;
} fake_va_list;
// malloc would do it as well!
// but alloca frees the mem after leaving this method
unsigned long *p = (unsigned long*)alloca(_args.size() * sizeof(unsigned long));
fake_va_list.packedArray = p;
ULVector::iterator i = _args.begin();
for (int n=0; i != _args.end(); i++, n++) {
p[n] = *i;
}
char buffer[512];
const char* fmt = _format.c_str();
vsprintf(buffer, fmt, fake_va_list.varargs);
// place a free(p) here if you used malloc
return string(buffer);
}
};
ostream& operator <<=(ostream &os, Format &obj) {
os << obj.format();
return os;
}
int main()
{
// we use '<<=' operator here which has lower precedence than '<<'
// otherwise we have to write
// cout << ( Format("\n%x %s %x %c\n") << etc. );
cout <<= Format("\n%x %s %x %c\n") << 0x11223344 << "VectorToVarArg" << 0xAABBCCDD << '!';
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括从你自己给出的答案来看,听起来你可以利用它
示例:
#include <iostream>
#include <string>
#include <sstream>
#include <boost/format.hpp>
using namespace std;
using namespace boost;
template <typename T>
string formatted_str_from_vec(const T& v) {
ostringstream fs;
size_t count = 1;
for (const auto& i : v) {
if (&i != &v[0]) {
fs << " ";
}
fs << '%' << count << '%';
++count;
}
format fmtr(fs.str());
for (const auto& i : v) {
fmtr % i;
}
// looks like fmtr("%1% %2% %3% %4%") % v[0] % v[1] etc.
return fmtr.str();
}
int main() {
cout << formatted_str_from_vec(vector<int>({1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12})) << endl;
cout << formatted_str_from_vec(vector<string>({"a", "b", "c"})) << endl;
format test1("%1% %2% %3%");
test1 % 1 % "2" % '3';
cout << test1.str() << endl;
format test2("%i %s %c");
test2 % 1 % "2" % '3';
cout << test2.str() << endl;
format test3("%1% %2%");
test3.exceptions(io::no_error_bits);
test3 % 'g';
cout << test3.str() << endl;
format test4("%%1%% = %1%");
test4 % "zipzambam";
cout << test4.str() << endl;
}
// g++ -Wall -Wextra printvector.cc -o printvector -O3 -s -std=c++0x
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
模板
字符串格式的\u str\u from\u vec(常量T&v){
ostringstream fs;
大小\u t计数=1;
用于(常数自动和i:v){
如果(&i!=&v[0]){
据我所知,不可能“伪造”你自己的va_arg列表。你可以通过重载函数f()直接传递向量。我不想重新实现va_arg,我只想模拟一个堆栈供va_arg操作。这看起来很有趣!现在谢谢!我将报告结果。谢谢你的有用提示!假设它只是关于打印。为了简单起见,我将v定义为向量。不过,这应该只是我自己的一个起点。以防万一v将被更改为包含不同的POD类型,我想使用vprintf()格式。好的,使用这里介绍的方法可以获得完整的答案:但是,由于不同的许可证,我不能简单地复制这里的代码。我提到这是一部分
#include <iostream>
#include <string>
#include <sstream>
#include <boost/format.hpp>
using namespace std;
using namespace boost;
template <typename T>
string formatted_str_from_vec(const T& v) {
ostringstream fs;
size_t count = 1;
for (const auto& i : v) {
if (&i != &v[0]) {
fs << " ";
}
fs << '%' << count << '%';
++count;
}
format fmtr(fs.str());
for (const auto& i : v) {
fmtr % i;
}
// looks like fmtr("%1% %2% %3% %4%") % v[0] % v[1] etc.
return fmtr.str();
}
int main() {
cout << formatted_str_from_vec(vector<int>({1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12})) << endl;
cout << formatted_str_from_vec(vector<string>({"a", "b", "c"})) << endl;
format test1("%1% %2% %3%");
test1 % 1 % "2" % '3';
cout << test1.str() << endl;
format test2("%i %s %c");
test2 % 1 % "2" % '3';
cout << test2.str() << endl;
format test3("%1% %2%");
test3.exceptions(io::no_error_bits);
test3 % 'g';
cout << test3.str() << endl;
format test4("%%1%% = %1%");
test4 % "zipzambam";
cout << test4.str() << endl;
}
// g++ -Wall -Wextra printvector.cc -o printvector -O3 -s -std=c++0x