美文网首页
c++模板匹配导致的死循环

c++模板匹配导致的死循环

作者: help_youself | 来源:发表于2019-05-07 10:24 被阅读0次
    #include <iostream>
    #include <utility>
    #include <memory>
    #include <stdio.h>
    template<typename T, typename... Ts>
    std::unique_ptr<T> make_unique(Ts&&... params)
    {
        return std::unique_ptr<T>(new T(std::forward<Ts>(params)...));
    
    }
    class Executor{
    public:
        virtual ~Executor(){}
        virtual bool Run()=0;
    };
    template <class Closure>
    class ClosureExector:public Executor{
    public:
        explicit ClosureExector(Closure &&closure):
        closure_(std::forward<Closure>(closure)){}
        ~ClosureExector(){
        }
    private:
        bool Run() override{
            closure_();
            return true;
        }
        typename std::decay<Closure>::type closure_;
    };
    template<class Closure>
    std::unique_ptr<Executor> ToTask(Closure &&closure)
    {
        return make_unique<ClosureExector<Closure>>(std::forward<Closure>(closure));
    }
    class Callback{
    public:
        Callback(){}
        void Call(){
            if(exec_){
                exec_->Run();
            }else{
                printf("wtf\n");
            }
        }
        //but this operation is problematic
        // PostTask(make_unique<ClosureExector<Closure>>(std::forward<Closure>(closure)))
        //使用这个语句导致编译很慢
        template <class Closure>
        void PostTask(Closure &&closure){
           //PostTask(make_unique<ClosureExector<Closure>>(std::forward<Closure>(closure)));
           PostTask(ToTask(std::forward<Closure>(closure)));
        }
        void PostTask(std::unique_ptr<Executor> exec){
            exec_=std::move(exec);
        }
        // if add this ,PostTask(make_unique.. seems work normal again.
        /*template <class Closure>
        void PostTask(std::unique_ptr<ClosureExector<Closure>> exec){
            printf("match2\n");
            std::unique_ptr<Executor> cast=std::move(exec);
            PostTask(std::move(cast));
        }*/
    private:
        std::unique_ptr<Executor> exec_;
    };
    void Test1(Callback *call){
        call->Call();
    }
    void Test2(Callback *call){
        int a=1,b=2;
        call->PostTask([a,b](){
            printf("%d,%d\n",a,b);
                       });
    }
    int main(){
        Callback call;
        Test2(&call);
        Test1(&call);
        call.Call();
        return 0;
    }
    

     我发现这个语句导致很长的编译时间,甚至不能成功编译。

        template <class Closure>
        void PostTask(Closure &&closure){
           PostTask(make_unique<ClosureExector<Closure>>(std::forward<Closure>(closure)));
        }
    

     但是增加了如下的强制类型转换又可以正常工作了。

        template <class Closure>
        void PostTask(Closure &&closure){
           PostTask(make_unique<ClosureExector<Closure>>(std::forward<Closure>(closure)));
        }
        template <class Closure>
        void PostTask(std::unique_ptr<ClosureExector<Closure>> exec){
            std::unique_ptr<Executor> cast=std::move(exec);
            PostTask(std::move(cast));
        }
    

     刚开始我并不知道是什么原因,导致了非常长的编译时间。不断写函数测试,模拟这个情况,灵光乍现,我觉是这个原因,模板函数在匹配的过程中,引起了死循环。

    template <class Closure>
     void PostTask(Closure &&closure){
        PostTask(make_unique<ClosureExector<Closure>>(std::forward<Closure>(closure)));
    //这里并不会调用void PostTask(std::unique_ptr<Executor> exec),
    而是会不断调用自己,引起一个死循环,不断调用自己,累死编译器。
     }
    

     And a similar case:

    #include <iostream>
    #include <utility>
    #include <memory>
    #include <stdio.h>
    template<typename T, typename... Ts>
    std::unique_ptr<T> make_unique(Ts&&... params)
    {
        return std::unique_ptr<T>(new T(std::forward<Ts>(params)...));
    
    }
    class Interface{
    public:
        virtual void Print()=0;
        virtual ~Interface(){}
    };
    template <typename T>
    class Parent: public Interface{
    public:
        Parent(T t):t_(t){}
        virtual void Print(){
            std::cout<<t_<<std::endl;
        }
        virtual ~Parent(){
        }
    private:
        T t_;
    };
    template <typename T>
    class Child:public Parent<T>{
    public:
        Child(T t):Parent<T>(t){}
        virtual void Print(){
            Parent<T>::Print();
            printf("hello child\n");
        }
        ~Child(){}
    };
    class Call{
    public:
        Call(){}
        ~Call(){
            if(exec_){
                delete exec_;
            }
        }
        void CallFun(){
            if(exec_){
                exec_->Print();
            }else{
                printf("wtf\n");
            }
        }
        template<class T>
        void Post(T t){
            Child<T>* e=(new Child<T>(t));
    
            Post((Interface*)e);
        }
        void Post(Interface* exec){
            printf("post\n");
            exec_=exec;
        }
    private:
        Interface *exec_{nullptr};
    };
    
    int main(){
        Call call;
        call.Post(12);
        call.CallFun();
        return 0;
    }
    
    
    

    相关文章

      网友评论

          本文标题:c++模板匹配导致的死循环

          本文链接:https://www.haomeiwen.com/subject/jdnsoqtx.html