C++ 传递标准::向量<;int>;变量函数项

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

我使用的是GCC4.6。 假设有一个参数向量v,我必须传递给一个可变函数f(const char*format,…)

一种方法是:

        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()的预期结构,即像堆栈一样

  • 这样做可行吗
  • 或者,是否可以使用一些内联汇编程序魔术将向量项值推送到实际堆栈上, 调用函数f(),然后清理堆栈
  • 最后,我不关心的事情:

  • 代码可能不可移植。好的,我只是对gcc感兴趣
  • 可能还有其他涉及预处理器黑客的方法
  • 对于Prtff()的格式化,使用变量函数,对于C++是不鼓励的。
  • 可变模板函数的使用

  • 您可以使用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好的,这里有一个部分解! 部分,因为它不适用于真正的可变函数, 但对于那些接受一份清单作为论据的人来说。 但我认为完整的解决方案并不遥远

    它基于我在这里找到的示例:

  • 动态创建虚拟联盟列表

  • 打造一个虚拟列表

  • 此代码在linuxVC++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