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>();
}
};
如何为上面的两个实现定义一个公共接口类,以便为此接口定义std::vector<T> foo()
?忽略函数的实现是相同的。
更新
我正在写一个Container类,它代表通过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分离内存表示,就像我为Container做的那样。
我不确定如何让Foo摆脱其内存实现。我的一个想法是使getMember虚拟化,以便引入可能不同的实现,但这不适用于模板化函数。
答案 0 :(得分: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>();
}