2

find_if、count_ifなどのstlアルゴリズムの述語を設計する必要があります。

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」メソッドでそれらの特定のクラスについて知らないプロジェクトライブラリの1つに配置したいので、特定のタイプを指定して単にオーバーロードすることはできません。

名前空間がない限り、クラス特性を使用したソリューションは適切です。述語Finderは「lib」名前空間にあり、「getData」を持つクラスは「program」名前空間にあります。

ありがとう。

4

4 に答える 4

3

なぜテンプレート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_;
};

これらすべてのメソッドの欠点は、ある時点で、使用するメソッドにそれらを分割できるようにするためにタイプを知る必要があることです。

于 2009-03-01T18:48:09.117 に答える
1

テンプレートについては、Veldhuizenのホームページをご覧くださいswitch。おそらくこれを使用して正確な演算子を選択できますか?

于 2009-03-01T17:59:50.307 に答える
0

SFINAEを使用して、あるタイプを別のタイプに変換できるかどうかをテストできるため、Javaインターフェイスとして機能する「機能タイプ」(たとえば、タイプ「has_function1」)からタイプを派生させることができます。

あなたが興味を持っているなら、私はそれを調べてあなたにもっと詳細な答えを与えることができます。

編集: Boostライブラリが利用できないとおっしゃっていましたが、Boost :: is_convertibleを機能させるために必要ないくつかのファイルを取得するのを妨げるものはありますか?特にコンパイルするものはありません!

于 2009-03-01T18:03:42.217 に答える