2
class Foo1: public IFoo
{
public:
    template <class T>
    std::vector<T> foo()
    {
        return std::vector<T>();
    }
};

class Foo2: public IFoo
{
public:
    template <class T>
    std::vector<T> foo()
    {
        return std::vector<T>();
    }
};

このインターフェース用に定義されているような、上記の 2 つの実装に共通のインターフェース クラスを定義するにはどうすればよいstd::vector<T> foo()ですか? 関数の実装が同一であることは無視してください。

アップデート:

C API 経由で送信されるデータを表す Container クラスを作成しています。

私のコンテナのインスタンスは、 などの特定のタイプのデータを格納しますContainer<int>, Container<std::string> and Container<Foo>

C API は非常にぎこちない方法でデータを返しますが、これは将来変更される可能性があります。データを std::list や std::vector などにコピーすることは可能ですが、C API から非常に多くのデータが渡されるため、これで問題ないかどうかはまだわかりません。

このため、Container クラスは、データが実際にどのように格納されるかから独立している必要があります。次のように、コンストラクターに渡す Getter クラスと Setter クラスを使用してこれを実現します。

Container<int>(Getter1<int>(uglyCApiContainer),Setter1<int>(uglyCApiContainer));

したがって、C API がデータを格納する方法を扱う Getter1 と Getter2 を放棄すると、コンテナの作成を変更するだけで済みます。

しかし、このデザインには問題があります。タイプ Foo。

Foo は、一連のコンテナーを含む複合型です。現時点では、次のようになります。

class Foo
{
public:
        ...
    template <class V>
    Container<V> getMember(std::string& memberName)
};

したがって、特定の Foo は、さまざまなタイプのコンテナーのセットを持つことができます。これらのメンバーの型は、モデルに格納されているため、事前にわかっています。Foo は現在、醜い C API メモリ実装のラッパーですが、コンテナに対して行ったように、Foo についてもメモリ表現を分離したいと考えています。

Foo をメモリ実装から解放する方法がわかりません。私が持っていた 1 つのアイデアは、おそらく異なる実装を導入するために getMember を仮想化することでしたが、これはテンプレート化された関数では不可能です。

4

1 に答える 1

2

タグのディスパッチと仮想継承を使用したソリューションは次のとおりです。

#include <vector>

template<typename T> struct tag {};

template<typename T> class IFooImpl {
public:
    virtual std::vector<T> getImpl(tag<T>) = 0;
};

class IFoo: public virtual IFooImpl<char>, virtual IFooImpl<int>
{
public:
    template<typename T> std::vector<T> get() {
        return static_cast<IFooImpl<T> *>(this)->getImpl(tag<T>{});
    }
};

template<typename T>
class FooImpl: public virtual IFooImpl<T> {
public:
    std::vector<T> getImpl(tag<T>) { return {}; }
};

class Foo: public IFoo, FooImpl<char>, FooImpl<int> {
};

int main() {
    Foo().get<char>();
}

charサポートされている型がカバーされている場所 (ここと)で少し繰り返しがありますがint、それは可変個引数テンプレートの継承で回避できます。

#include <vector>

template<typename T> struct tag {};

template<template<typename> class C, typename... Types> class Inherit {};
template<template<typename> class C, typename T, typename... Rest>
class Inherit<C, T, Rest...>: public C<T>, Inherit<C, Rest...> {};

template<typename T> class IFooImplV {
public:
    virtual std::vector<T> getImpl(tag<T>) = 0;
};
template<typename T> class IFooImpl: public virtual IFooImplV<T> {};

template<typename... Types> class IFoo: public Inherit<IFooImpl, Types...> {
public:
    template<typename T> std::vector<T> get() {
        return static_cast<IFooImpl<T> *>(this)->getImpl(tag<T>{});
    }
};

template<typename T> class FooImpl: public IFooImpl<T> {
public:
    std::vector<T> getImpl(tag<T>) { return {}; }
};

template<typename... Types> class FooMulti:
    public IFoo<Types...>, Inherit<FooImpl, Types...> {};
class Foo: public FooMulti<char, int> {};

int main() {
    Foo().get<char>();
}
于 2012-09-06T15:15:08.233 に答える