微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 传递对Variadic模板的引用

我正在处理一个事件库,而我正在面对Variadic模板的问题.

所有的工作非常好,除了我不能传递引用作为参数的事实…

这是一个非常简化的例子,用来揭示我的问题.

struct DelayedSignal 
{   
    ~DelayedSignal ()
    { std::cout << "~DelayedSignal CLOSE" << std::endl; }

    template<class C,class... Args>
    DelayedSignal ( void(C::*func)(Args...),C& obj )
    { std::cout << "DelayedSignal INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }

    template<class C,C& obj,Args... args )
    {
        std::cout << "DelayedSignal INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
    }
};

template<class... ArgsBis>
struct DelayedSignal_DebugHelper 
{
    ~DelayedSignal_DebugHelper ()
    { std::cout << "~DelayedSignal_DebugHelper CLOSE" << std::endl; }

    template<class C,class... Args>
    DelayedSignal_DebugHelper ( void(C::*func)(Args...),C& obj )
    { std::cout << "DelayedSignal_DebugHelper INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }

    template<class C,ArgsBis... args ) // Need to use ArgsBis instead of Args to make it work
    {
        std::cout << "DelayedSignal_DebugHelper INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
    }
};


template < class Tr,class... Args >
struct Signal
{
    void fire ( Args... args ) { std::cout << "Signal::fire::" << sizeof...(Args) << std::endl; }
};

struct Klass {};


int main()
{
    std::string str1("Blop");   // Will be used as reference
    Klass k;                    // Will be used as reference

    Signal<void,Klass&> signal_01;
    Signal<void,std::string&> signal_02;

    std::cout << "====== DelayedSignal :: needed for production purpose ===============" << std::endl;

    // OK
    DelayedSignal test01(&Signal<void,std::string&>::fire,signal_02);
    // HERE IS THE PROBLEM
    //DelayedSignal test02(&Signal<void,signal_02,str1);

    // OK
    DelayedSignal test03(&Signal<void,Klass&>::fire,signal_01);
    // HERE IS THE PROBLEM
    //DelayedSignal test04(&Signal<void,signal_01,k);

    std::cout << "====== DelayedSignal_DebugHelper :: used only for debug purpose ======" << std::endl;

    // OK
    DelayedSignal_DebugHelper<std::string&> test05(&Signal<void,signal_02);
    // OK
    DelayedSignal_DebugHelper<std::string&> test06(&Signal<void,str1);

    // OK
    DelayedSignal_DebugHelper<Klass&> test07(&Signal<void,signal_01);
    // OK
    DelayedSignal_DebugHelper<Klass&> test08(&Signal<void,k);

    return 1;
}

当我将所有DelayedSignal实例注册到单个std :: list实例中时,我想避免在类本身使用模板,这就是为什么我在构造函数上使用模板.我也可以使用一个纯虚拟类作为所有DelayedSignal的基础,并将虚拟类的注册注册到std :: list中,但我认为最好最小化虚拟方法的使用,我真的很感兴趣这个问题?

正如你在这个例子中看到的那样,如果test02和test04被激活,返回错误.
DelayedSignal_DebugHelper与DelayedSignal几乎相同,除了在最后一个构造函数(而不是Args模板(方法模板参数))中使用ArgsBis(一个类模板参数),否则它不起作用(与DelayedSignal一样). Args被接受在void(C :: * func)(Args …)上,但不是与ArgsBis … args排除它们在同一个构造函数声明中的事实.

据我所知,只要没有参考(DelayedSignal test04(& Signal< void,Klass> :: fire,k)),或者有多个参数(或没有)引用.

有没有办法解决这个问题?

谢谢.

解决方法

Howard Hinnant是对的…另一种可能性是使用任何地方的引用,例如:
#include <iostream>

struct DelayedSignal 
{   
    ~DelayedSignal ()
     { std::cout << "~DelayedSignal CLOSE" << std::endl; }

    template<class C,class... Args>
    DelayedSignal ( void(C::*func)(Args &...),Args & ... args )
    {
        std::cout << "DelayedSignal INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
    }
};

template < class Tr,class... Args >
struct Signal
{
     void fire ( Args &... args ) { std::cout << "Signal::fire::" << sizeof...(Args) << std::endl; }
};

struct Klass {};

int main()
{
    std::string str1("Blop");   // Will be used as reference
    Klass k;                    // Will be used as reference

    Signal<void,signal_02);
    // HERE IS THE PROBLEM
    DelayedSignal test02(&Signal<void,str1);

}

原文地址:https://www.jb51.cc/c/116030.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐