美文网首页
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