为原始指针,智能指针和值创建成员函数的编译时变化

时间:2017-03-22 12:13:37

标签: c++ templates

我的课程如下。我封装了矢量来摆脱for循环。可以在link中找到工作示例(感谢评论部分的帮助)

    template<class T, class U>
    std::shared_ptr<T> Cast( const std::shared_ptr<U>& spObject )   // rename from CastTerrainObject
    {
        return std::dynamic_pointer_cast<T>(spObject);
    }

    template<class T, class U>
    T Cast( U* r)
    {
        return dynamic_cast<T>(r);
    }

    template<typename value> 
    struct A 
    {

        template < typename T, typename F >
        T Find( F filterFunction)
        {
            return DoFind<T>(filterFunction, std::is_pointer<T>());
        }

        template < typename T, typename F >
        T DoFind( F filterFunction, std::true_type)
        {
            for ( size_t i = 0; i < iteratableList.size(); i++)
            {
                auto castedTerrain = Cast<T>(iteratableList[i]);
                if ( castedTerrain && filterFunction(castedTerrain) )
                    return iteratableList[i];
            }
            return T();
        }


        template < typename T, typename F >
        T DoFind( F filterFunction, std::false_type)
        {
            for ( size_t i = 0; i < iteratableList.size(); i++)
            {
                auto castedTerrain =  Cast<typename T::element_type>(iteratableList[i]);
                if ( castedTerrain && filterFunction(castedTerrain) )
                    return iteratableList[i];
            }
            return T();
        }

        std::vector<value> iteratableList;
    }

我的课程适用于智能指针

std::vector<std::shared_ptr<std::string>> names = {  make_shared("needle"), make_shared("manyOtherNames") } ; 
A<std::shared_ptr<std::string>> iterateable{ names }; 
iterateable.Find<std::shared_ptr<std::string>>([] ( std::shared_ptr<std::string> ){ return *in == "needle";});

和原始指针

std::vector<std::string*> names = {  new std::string("needle"), new std::string("manyOtherNames") } ; 
A<std::string*> iterateable{ names }; 
iterateable.Find<std::string*>([] ( std::string* in ){ return *in == "needle";});

但现在我想将它与值一起使用(std :: string只是一个例子,我希望我的类能够处理任何非指针和非智能指针类型):

std::vector<std::string> names = {  "needle", "manyOtherNames" } ; 
A<std::string> iterateable{ names }; 
iterateable.Find<std::string>([] ( std::string in ){ return in == "needle";});

我还需要一个DoFind,但我看不到我的案例的类型特征。 如何组织代码以实现我的需求。我仅限于Visual Studio 2010.

1 个答案:

答案 0 :(得分:1)

您的代码存在一些问题:

  1. 你的lambda没有返回布尔值:
  2. 此:

    [] ( std::string in ){ in == "needle";}
    

    应该是:

    [] ( std::string in ){ return in == "needle";}
    
    1. 为什么要尝试在非指针类型上执行dynamic_cast?请使用static_cast
    2. 改变这个:

      Cast<typename T::element_type>(iteratableList[i]);
      

      进入这个:

      static_cast<T>(iteratableList[i]);
      
      1. 但是,由于您需要保留Cast函数,因此定义另一个重载以接受值就足够了,只留下三个版本。
      2. 请注意,我修改了您的shared_ptr版本,因为它不正确。

        template<class T, class U>
        T Cast(const U& r)
        {
            return static_cast<T>(r);
        }
        
        template<class T, class U>
        T Cast(const std::shared_ptr<U>& spObject)
        {
            return std::dynamic_pointer_cast<typename T::element_type>(spObject);
        }
        
        template<class T, class U>
        T Cast( U* r)
        {
            return dynamic_cast<T>(r);
        }
        

        Live Demo