boost::any、变体、基于它们的数组调用函数

发布于 2024-09-18 09:01:59 字数 2336 浏览 11 评论 0原文

给定一组函数,例如: <代码>

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

模板 无效 Go(A1 a1, A2 a2);

模板 无效 Go(A1 a1, A2 a2, A3 a3);

Is it possible to take an array of some variant type and given its contents, fire the correct function? My application for this is that I want to pass a set of parameters X, to another process, where I only have the option of passing a single pointer. My idea was to send a pointer to a std::vector<boost::any> and then to somehow work out which of the above methods to fire given its contents.

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

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



#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
    }
}

Given a set of functions, such as:

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

template<class A1, class A2> Void Go(A1 a1, A2 a2);

template<class A1, class A2, class A3> Void Go(A1 a1, A2 a2, A3 a3);


Is it possible to take an array of some variant type and given its contents, fire the correct function? My application for this is that I want to pass a set of parameters X, to another process, where I only have the option of passing a single pointer. My idea was to send a pointer to a std::vector<boost::any> and then to somehow work out which of the above methods to fire given its contents.

This concerns my experiments with cross-thread eventing and communication, hence it may seem unnecessarily esoteric!

Edit: ok, for example, this is the intention. Obviously it doesn't compile (the template resolution occurs at compile-time, but I want to determine which function to call at run-time!):



#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
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

赤濁 2024-09-25 09:01:59

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

Yes, boost::variant knows the value type that it currently stores. It allows visitation and calls the correct overloaded operator(). boost::any uses a fundamental different technique and can't tell you what it currently stores.

荭秂 2024-09-25 09:01:59

好的,我在这方面取得了一些进展。如果我使用 boost::any 数组,我可以在 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 向量,调用函数在具有正确数量和类型的某些对象上。

Ok, I made some progress with this. If I use an array of boost::any, I can convert to and from a void * (and hence pass it as an lParam in a custom window message to a msgProc). The solution is if both sender and receiver classes have the same template parameters. That is to say, something like this (should compile as a console project in 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();
}

The above demonstrates going from a vector of boost::any to a void * and then back to a vector of boost::any, calling a function on some object with the correct arity and types.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文