سؤال

أحتاج إلى تصميم مسند لخوارزميات stl مثل find_if وcount_if.

namespace lib
{
    struct Finder
    {
        Finder( const std::string& name ):
            name_( name )
        {
        }

        template< typename TElement >
        bool operator( const TElement& element )
        {
            return element.isPresent( name_ );
        }

        /* template< typename TElement >
        bool operator( const TElement& element )
        {
            const Data& data = element.getData();
            return data.isPresent( name_ );
        }*/ 
    };
}

لكنني أحتاج إلى عوامل تشغيل مختلفة () وفقًا لوجود بعض الأساليب المحددة في TElement.كما لو كانت تحتوي على "getData" أود التحقق من تلك البيانات وإذا لم تكن كذلك فسأقوم ببعض الإجراءات الأخرى.

أنا على علم بـ SFINAE.لكن ليس لدي دفعة::حول المشروع.لذلك إما أن يكون هناك بعض التنفيذ السهل للقالب "has_method" أو أنك تعرف بعض حلول التصميم الأخرى.

لا يمكنني الإشارة إلى أنواع محددة والتحميل الزائد ببساطة لأنني أرغب في وضع هذا المسند على إحدى مكتبة المشروع، التي لا تعرف شيئًا عن تلك الفئات المحددة باستخدام طريقة "getData".

الحل مع سمات الفصل جيد بقدر ما لا توجد مساحات أسماء.الباحث عن المسند في مساحة الاسم "lib" والفئة التي تحتوي على "getData" موجودة في مساحة الاسم "البرنامج".

شكرًا.

هل كانت مفيدة؟

المحلول

لماذا استخدام قالب mathods لفي كل شيء؟ مجرد استخدام فئة معينة التي تريد وضعها على أساس أو الفئات الأساسية المشتركة إذا كان هناك الكثير من أنواع الطبقة.

ومنها مثلا.

struct Finder
{
    Finder( const std::string& name ):
        name_( name )
    {
    }

    bool operator( const IsPresentBaseClass& element )
    {
        return element.isPresent( name_ );
    }

    bool operator( const GetDataBaseClass& element )
    {
        const Data& data = element.getData();
        return data.isPresent( name_ );
    } 
 };

إذا هذا النمط يحدث كثيرا مع أنواع فئة مختلفة وكنت تعرف أنواع قبل استخدام المسند هل يمكن أن القالب المسند نفسها.

ومنها مثلا.

template<class T1, class T2>
struct Finder
{
    Finder( const std::string& name ):
        name_( name )
    {
    }

    bool operator( const T1& element )
    {
        return element.isPresent( name_ );
    }

    bool operator( const T2& element )
    {
        const Data& data = element.getData();
        return data.isPresent( name_ );
    } 
 };

وأو نهج آخر هل يمكن استخدام هو استخدام نوع من الصفات فئة لاستيعاب معلومات.

ومنها مثلا.

struct UseIsPresent
{
    template<class T>
    static bool CompareElement( const T& element, const std::string& name )
    {
        return element.isPresent( name );
    }
};

struct UseGetData
{
    template<class T>
    static bool CompareElement( const T& element, const std::string& name )
    {
        const Data& data = element.getData();
        return data.isPresent( name );
    } 
};

// default to using the isPresent method
template <class T>
struct FinderTraits
{
    typedef UseIsPresent FinderMethodType;
};

// either list the classes that use GetData method
// or use a common base class type, e.g. UseGetData
template <>
struct FinderTraits<UseGetData>
{
    typedef UseGetData FinderMethodType;
};

struct Finder
{
    Finder( const std::string& name )
    : name_( name )
    {
    }

    template<class T>
    bool operator()( const T& element )
    {
        return FinderTraits<T>::FinderMethodType::CompareElement<T>(element, name_);
    }

    std::string name_;
};

وسلبيات كل من هذه الأساليب هي أنه عند نقطة معينة أنت بحاجة إلى معرفة أنواع لتكون قادرة على تقسيمها إلى الطريقة التي يجب استخدامها.

نصائح أخرى

scroll top