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

Making compile time variations of a member function for raw pointers, smart pointers and values

本文关键字:指针 函数 编译 成员 创建 原始 智能      更新时间:2023-10-16

我有如下类。我封装了向量以摆脱 for 循环。工作示例可以在链接中找到(感谢评论部分的帮助(

    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. 您的 lambda 没有返回布尔值:

这:

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

应该是:

[] ( std::string in ){ return in == "needle";}
  1. 为什么要尝试对非指针类型执行dynamic_cast? 对它们使用static_cast

更改此设置:

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

进入这个:

static_cast<T>(iteratableList[i]);
  1. 但是,由于您需要保留Cast函数,因此定义另一个重载以接受值就足够了,因此我们有三个版本。

请注意,我修改了您的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);
}

现场演示