问题描述
我经常不得不在C ++中实现“类似容器”的类,而且我发现我常常忘记实现接口的一部分,以后会遇到问题。为了解决这个问题,我想创建一个抽象的Container
类,如果没有实现任何必需的接口函数,我可以使我的容器类继承自该类。
问题在于容器类通常定义一个size_type
,而我希望size()
函数返回相应的size_type
,无论底层容器是什么。
以下是我所谈论的内容的简化示例:
#include <vector>
// Abstract class
template <typename T>
class Container
{
public:
virtual ~Container() = 0;
//********************************************************************************
// How do I tell it to return whatever "size_type" is for the child class?
//********************************************************************************
virtual typename ChildClass::size_type size() const = 0;
};
template <typename T>
Container<T>::~Container() = default;
// Concrete
template <typename T>
class MyVector final : public Container<T>
{
public:
// size_type of the child class defined here
using size_type = typename std::vector<T>::size_type;
MyVector()
: m_data()
{}
size_type size() const override
{
return m_data.size();
}
private:
std::vector<T> m_data;
};
在size_type
的抽象函数定义中,有什么方法可以引用子类的size()
吗?
编辑
在应用CRTP之后(建议如下),我觉得自己距离更近了,但是仍然无法编译第二个实例化MyVector<double>
对象的对象:
// Abstract class
template <typename T>
class Container {
public:
virtual ~Container() = default;
// Still can't seem to resolve the type here
virtual typename T::size_type size() const = 0;
};
// Concrete
template <typename T>
class MyVector final : private Container<MyVector<T>> {
public:
using size_type = typename std::vector<T>::size_type;
using value_type = T;
size_type size() const
{
return m_data.size()
}
private:
std::vector<T> m_data;
};
int main()
{
// Fails to compile
MyVector<double> v;
}
我收到编译器错误:
错误C2039:'size_type':不是'MyVector'的成员
解决方法
从answer到一个相关的问题,我发现了一些可行的方法。这有点丑陋,因为它要求我为我要实现的每个容器定义一个ContainerTraits
结构,但确实可以完成工作。
template <typename T>
struct ContainerTraits;
// Abstract class
template <typename T>
class Container {
public:
using size_type = typename ContainerTraits<T>::size_type;
virtual ~Container() = default;
virtual typename size_type size() const = 0;
};
// Concrete
template <typename T>
class MyVector final : private Container<MyVector<T>> {
public:
using size_type = typename ContainerTraits<MyVector>::size_type;
size_type size() const override { return m_data.size(); }
private:
std::vector<T> m_data;
};
template <typename T>
struct ContainerTraits<MyVector<T>>
{
using size_type = typename std::vector<T>::size_type;
};
,
我在想...您如何将类型名称传递给类? 作为模板参数!
因此您可以执行以下操作:
#include <vector>
// interface
template <
/*typename container_type,// not required in this example */
typename size_type
>
class Container {
public:
virtual ~Container() = default;
virtual size_type size() const = 0;
};
template <
typename value_type,typename size_type = typename std::vector<value_type>::size_type
>
class MyVector final :
public Container<
/*MyVector<T>,*/
size_type
>
{
public:
size_type size() const
{
return m_data.size();
}
private:
std::vector<value_type> m_data;
};
int main()
{
MyVector<double> v;
}