如何在C++中设计库包装器

How to design a library wrapper in C++?

本文关键字:设计库 包装 C++      更新时间:2023-10-16

我想用简单的语法设计一个C++包装器:

Vector<double,stl> v; // aka std::vector<double>
Vector<double, eigen> w; // aka Eigen::VectorXd from Eigen library
Matrix<double, eigen> m; // aka Eigen::MatrixXd from Eigen library

但是,我无法获得此语法,尤其是对于最后两个示例。这是我在包装 STL 向量的情况下的代码:

#ifndef WRAPPER_HPP
#define WRAPPER_HPP
#include <cstdlib>
#include <vector>
//=============
// BASE WRAPPER
//=============
template<class ScalarType, template<class,class...> class WrappedType>
class Wrapper
{
protected:
  WrappedType<ScalarType> wrapped_;
};
//==============
// STL WRAPPER
//==============
template<class ScalarType, template<class,class...> class WrappedType>
struct stl;
template<class ScalarType>
struct stl<ScalarType,std::vector> : public Wrapper<ScalarType,std::vector>
{
public:
  size_t size()
  { return this->wrapped_.size(); }
};
//=======
// VECTOR
//=======
template<class ScalarType, template<class, template<class,class...> class> class Wrapper>
using Vector = Wrapper<ScalarType,std::vector>;
// **** Problem : I should not provide "std::vector" above ****
#endif

STL 包装器是一种称为 stl 的结构。此结构实际上是 Wrapper 类的子类。我有专门的STL结构来研究STL的向量。我可能会对某些容器(列表、地图等)进行其他规范。因此,当声明

Vector<double,stl> vec

我希望能够从这对(Vector,stl)中推断出它对应于stl对std::vector的专业化。但是,我无法做到这一点。每次我尝试某事时,我都会对模板参数进行无限递归。

可能有一个很好的方法可以使用一些 typedef 或模板别名来做到这一点,但我找不到它。可能是这样的:

template<class ScalarType, template<class, template<class,class...> class> class Wrapper>
using Vector = Wrapper<ScalarType,????>;

其中????等同于 std::vector,但从包装器推导出来。但我不知道这是否可能。

我的设计也可能很幼稚。我非常感谢任何改进它的建议。我只对代码的语法感兴趣。

谢谢!

使用 C++11 或更高版本的语法相当容易做到这一点。

下面是实现 Vector 包装器的示例,它将生成您要查找的语法。使用类似的方法来实现Matrix等。

该方法将模板专用化与template using 相结合,选择正确的专用化来声明成员类型,该成员类型是要声明的实际类型:

#include <vector>
class stl; // dummy class
class eigen; // dummy class
template<typename ...Args> class vector_impl;
template<>
class vector_impl<double, stl> {
public:
    typedef std::vector<double> impl_type;
};
template<>
class vector_impl<double, eigen> {
public:
    typedef Eigen::VectorXd impl_type;   // I presume...
};
// And the magical alias:
template<typename ...Args>
using Vector=typename vector_impl<Args...>::impl_type;

根据上述定义:

Vector<double, stl> a;    // This declares a std::vector<double>
Vector<double, eigen> b;  // This declares an `Eigen::VectorXd`

使用可变参数模板可以进行一些进一步的工作,即一些额外的调整也可能导致一些额外的工作,例如将自定义分配器类型转发到std::vector等......