代码之家  ›  专栏  ›  技术社区  ›  Robinson

Boost::任意,变量,基于它们的数组调用函数

  •  1
  • Robinson  · 技术社区  · 14 年前

    给定一组函数,例如:

    template<class A1>
    Void Go(A1 a);

    模板<A1类,A2类> 空转(a1 a2 a2);

    模板<A1、A2、A3> 空转(a1 a2 a2 a3 a3); 是否可以获取某个变量类型的数组并给出其内容,从而激发正确的函数?我的应用程序是要将一组参数x传递给另一个进程,在该进程中,我只能选择传递一个指针。我的想法是发送一个指向std::vector<boost::any>的指针,然后不知何故地计算出在给定内容的情况下要触发上面的哪些方法。

    这涉及到我的跨线程事件和通信实验,因此它可能看起来不必要的深奥!

    编辑:好的,例如,这就是目的。显然它没有编译(模板解析发生在编译时,但我想确定在运行时调用哪个函数!):

    
    
    #include <boost\any.hpp>
    
    #include <vector>
    #include <iostream>
    #include <string>
    
    
    class A
    {
    
    public:
    
        void Go()
        {
            std::cout << L"(0 params)\n";
        }
    
        template
        void Go(U0 u0)
        {
            std::cout << L"1 param " << u0 << L"\n";  
        }
    
        template
        void Go(U0 u0, U1 u1)
        {
            std::cout << L"2 params " << u0 << L" " << u1 << L"\n";   
        }
    
        template
        void Go(U0 u0, U1 u1, U2 u2)
        {
            std::cout << L"3 params " << u0 << L" " << u1 << L" " << u2 << L"\n"; 
        }
    
    };
    
    class B
    {
    
    public:
    
        void Whatever() {}
    
    };
    
    int main(int argc, wchar_t* argv[])
    {
        // Create a collection of variants.
    
        std::vector<boost::any> myVariants;
    
        B myB;
    
        myVariants.push_back(123);
        myVariants.push_back(std::wstring(L"Test"));
        myVariants.push_back(&myB);
    
    
    
        // Take a void pointer to them.
    
        void *variants = &myVariants;
    
    
    
        // Convert back into an array.
    
        std::vector<boost::any>& myConverted = *(std::vector<boost::any> *)(variants);
    
    
    
        // Fire the correct event on A.
    
        A myA;
    
        switch(myConverted.size())
        {
        case 0:
            myA.Go();
            break;
    
        case 1:
            myA.Go(myConverted[0]);
            break;
    
        case 2:
            myA.Go(myConverted[0], myConverted[1]);
            break;
    
        case 3:
            myA.Go(myConverted[0], myConverted[1], myConverted[2]);
            break;
    
        default: ;
            // throw
        }
    }
    
    
    2 回复  |  直到 10 年前
        1
  •  0
  •   Johannes Schaub - litb    14 年前

    对, boost::variant 知道它当前存储的值类型。它允许访问并调用正确的重载 operator() . boost::any 使用一种基本的不同技术,无法告诉您它当前存储的内容。

        2
  •  0
  •   Robinson    14 年前

    好吧,我在这方面取得了一些进展。如果我使用Boost::Any数组,我可以将其转换为void*,也可以从void*转换为void*(因此,可以将它作为自定义窗口消息中的lparam传递给msgproc)。解决方案是,如果发送方类和接收方类都具有相同的模板参数。也就是说,类似这样的东西(应该在2010年编译为一个控制台项目):

    
    
    #include <boost\any.hpp>
    
    #include <vector>
    #include <iostream>
    #include <string>
    
    // A class to receive the event.
    
    template<typename A0 = int, typename A1 = int, typename A2 = int>
    class A
    {
    
    public:
    
        void Go()
        {
            std::wcout << L"(0 params)\n";
        }
    
        void Go(A0 u0)
        {
            std::wcout << L"1 param " << u0 << L"\n"; 
        }
    
        void Go(A0 u0, A1 u1)
        {
            std::wcout << L"2 params " << u0 << L" " << u1 << L"\n";  
        }
    
        void Go(A0 u0, A1 u1, A2 u2)
        {
            std::wcout << L"3 params " << u0 << L" " << u1 << L" " << u2 << L"\n";    
        }
    
    };
    
    // A class to demonstrate passing an abitrary object.
    
    class B
    {
    
    public:
    
    
    };
    
    // Implement operator on type B so we can use std::cout.
    
    std::wostream& operator << (std::wostream& o, const B& b)
    {
        o << L"Hello!";
    
        return o; 
    }
    
    // A class that converts an array of boost::any from void and calls an appropriate function on A.
    
    template<typename A0 = int, typename A1 = int, typename A2 = int>
    class C
    {
    
    public:
    
        void Everything()
        {
    
            // Create a collection of variants.
    
            std::vector<boost::any> myVariants;
    
            B myB;
    
            myVariants.push_back(123);
            myVariants.push_back(myB);
    
    
    
            // Take a void pointer to them.
    
            void *variants = &myVariants;
    
    
    
            // Convert back into an array.
    
            std::vector<boost::any>& myConverted = *(std::vector<boost::any> *)(variants);
    
    
    
            // Fire the correct event on A.
    
            A<A0, A1, A2> myA;
    
            switch(myConverted.size())
            {
            case 0:
                myA.Go();
                break;
    
            case 1:
                myA.Go(boost::any_cast<A0>(myConverted[0]));
                break;
    
            case 2:
                myA.Go(boost::any_cast<A0>(myConverted[0]), boost::any_cast<A1>(myConverted[1]));
                break;
    
            case 3:
                myA.Go(boost::any_cast<A0>(myConverted[0]), boost::any_cast<A1>(myConverted[1]), boost::any_cast<A2>(myConverted[2]));
                break;
    
            default: ;
                // throw
            }
        }
    };
    
    int main(int argc, wchar_t* argv[])
    {
        C<int, B> c;
    
        c.Everything();
    }
    

    上面演示了如何从boost::any的向量转到void*然后返回boost::any的向量,对具有正确arity和类型的对象调用函数。