如何在 C++ 中设计库包装器?
How to design a library wrapper in C++?
我想用简单的语法在 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 的结构。这个结构实际上是Wrapperclass的subclass。我有专门用于 STL 向量的 stl 结构。我可能会为某些容器(列表、地图等)做一些其他的专业化。因此,当声明
Vector<double,stl> vec
我希望能够从对 (Vector, stl) 中推断出它对应于 std::vector 的 stl 特化。但是,我做不到。每次尝试时,我都会对模板参数进行无限递归。
可能有一个使用 typedef 或模板别名执行此操作的好方法,但我找不到它。可能是这样的:
template<class ScalarType, template<class, template<class,class...> class> class Wrapper>
using Vector = Wrapper<ScalarType,????>;
在哪里????将等同于 std::vector,但从 Wrapper 推导出来。但是不知道可不可以。
我的设计也可能很幼稚。我真的很感激任何改进它的建议。我只对代码的语法感兴趣。
谢谢!
使用 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
,等等...
我想用简单的语法在 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 的结构。这个结构实际上是Wrapperclass的subclass。我有专门用于 STL 向量的 stl 结构。我可能会为某些容器(列表、地图等)做一些其他的专业化。因此,当声明
Vector<double,stl> vec
我希望能够从对 (Vector, stl) 中推断出它对应于 std::vector 的 stl 特化。但是,我做不到。每次尝试时,我都会对模板参数进行无限递归。
可能有一个使用 typedef 或模板别名执行此操作的好方法,但我找不到它。可能是这样的:
template<class ScalarType, template<class, template<class,class...> class> class Wrapper>
using Vector = Wrapper<ScalarType,????>;
在哪里????将等同于 std::vector,但从 Wrapper 推导出来。但是不知道可不可以。
我的设计也可能很幼稚。我真的很感激任何改进它的建议。我只对代码的语法感兴趣。
谢谢!
使用 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
,等等...