为提供不同接口的容器包装容器
Wrapping container for containers providing diffrent interfaces
我想为 stl 容器创建通用 "wrapper",例如:
template<template <typename, typename...> class Container = std::vector >
class ContainerWrapper{
add();
size();
find();
resize();
sort();
/**/
}
+迭代器。
我希望成员函数具有不同的实现,具体取决于 Container 提供的方法。 C++ 模板系统足以创建这个吗?这甚至可能吗,只使用标准(没有提升,没有预处理器)?
我知道如何以困难的方式做到这一点 - 为每个 stl 容器编写模板专业化。但我希望它也能与其他容器一起工作,而且我正在寻找更通用的方法来做到这一点。
此外,这里有什么更好的?继承自 Container
还是将 Container
作为组件?
STL 容器不能被继承。 They do not have virtual destructors. It was discussed having the containers as final,但未完成,因为这会带来重大变化。
所以使用合成是你最好的选择。
前段时间我为我的一个项目开发了类似的东西。
我提取了一个完整的工作示例(原始代码更复杂)来展示如何使用方法 addVal()
(调用 push_back()
、push()
、insert()
或 push_front()
) 向包装容器添加一个值。
此代码适用于(如果我没记错的话)std::vector
、std::set
、std::multiset
、std::unordered_set
、std::unordered_multiset
、std::deque
, std::queue
, std::priority_queue
, std::forward_list
和 std::stack
.
其他容器(例如 std::array
)可能需要 cntWrp
.
的不同专业化
我不想解释每一行代码,但是,如果您有任何问题,我可以尝试回复(或者,如果您愿意,我可以给您 link 我的 github 项目).
例子
#include <set>
#include <vector>
#include <iostream>
#include <stdexcept>
#include <type_traits>
class emptyClass
{ };
template <typename ... Ts>
struct funcType;
template <typename T, typename ... Ts>
struct funcType<T, Ts...>
{ using type
= typename std::conditional<T::result,
typename T::type, typename funcType<Ts...>::type>::type; };
template <>
struct funcType<>
{ using type = emptyClass; };
#define methodCheck_1(meth) \
\
class helpMeth_1_##meth {}; \
\
template <typename T, typename A> \
struct isWithMethod_1_##meth \
{ \
template<typename U> \
static decltype(U().meth(A())) func (U*); \
\
template<typename U> \
static emptyClass func (...); \
\
static const bool result \
= ! std::is_same<emptyClass, \
decltype(func<T>(nullptr))>::value; \
\
using type = helpMeth_1_##meth; \
}
methodCheck_1(insert);
methodCheck_1(push);
methodCheck_1(push_back);
methodCheck_1(push_front);
template <typename>
class cntWrp;
template <template <typename ...> class C, typename X, typename ... Xs>
class cntWrp< C<X, Xs...> >
{
private:
using addModeType = typename funcType<
isWithMethod_1_push_back<C<X, Xs...>, X>,
isWithMethod_1_insert<C<X, Xs...>, X>,
isWithMethod_1_push<C<X, Xs...>, X>,
isWithMethod_1_push_front<C<X, Xs...>, X>>::type;
static constexpr addModeType addMode {};
void addVal (X const & x, helpMeth_1_push_back const)
{ val.push_back(x); }
void addVal (X const & x, helpMeth_1_push const)
{ val.push(x); }
void addVal (X const & x, helpMeth_1_insert const)
{ val.insert(x); }
void addVal (X const & x, helpMeth_1_push_front const)
{ val.push_front(x); }
void addVal (X const & x, emptyClass const)
{ throw std::runtime_error("cntWr<>::addVal without mode"); }
public:
C<X, Xs...> val {};
cntWrp ()
{ }
cntWrp (C<X, Xs...> const & v0) : val { v0 }
{ }
void addVal (X const & x)
{ addVal(x, addMode); }
};
int main ()
{
cntWrp<std::set<int>> csi;
csi.addVal(2);
csi.addVal(7);
csi.addVal(5);
std::cout << "set:" << std::endl;
for ( auto const elem : csi.val )
std::cout << elem << std::endl;
cntWrp<std::vector<int>> cvi;
cvi.addVal(2);
cvi.addVal(7);
cvi.addVal(5);
std::cout << "vector:" << std::endl;
for ( auto const elem : cvi.val )
std::cout << elem << std::endl;
}
我想为 stl 容器创建通用 "wrapper",例如:
template<template <typename, typename...> class Container = std::vector >
class ContainerWrapper{
add();
size();
find();
resize();
sort();
/**/
}
+迭代器。 我希望成员函数具有不同的实现,具体取决于 Container 提供的方法。 C++ 模板系统足以创建这个吗?这甚至可能吗,只使用标准(没有提升,没有预处理器)?
我知道如何以困难的方式做到这一点 - 为每个 stl 容器编写模板专业化。但我希望它也能与其他容器一起工作,而且我正在寻找更通用的方法来做到这一点。
此外,这里有什么更好的?继承自 Container
还是将 Container
作为组件?
STL 容器不能被继承。 They do not have virtual destructors. It was discussed having the containers as final,但未完成,因为这会带来重大变化。
所以使用合成是你最好的选择。
前段时间我为我的一个项目开发了类似的东西。
我提取了一个完整的工作示例(原始代码更复杂)来展示如何使用方法 addVal()
(调用 push_back()
、push()
、insert()
或 push_front()
) 向包装容器添加一个值。
此代码适用于(如果我没记错的话)std::vector
、std::set
、std::multiset
、std::unordered_set
、std::unordered_multiset
、std::deque
, std::queue
, std::priority_queue
, std::forward_list
和 std::stack
.
其他容器(例如 std::array
)可能需要 cntWrp
.
我不想解释每一行代码,但是,如果您有任何问题,我可以尝试回复(或者,如果您愿意,我可以给您 link 我的 github 项目).
例子
#include <set>
#include <vector>
#include <iostream>
#include <stdexcept>
#include <type_traits>
class emptyClass
{ };
template <typename ... Ts>
struct funcType;
template <typename T, typename ... Ts>
struct funcType<T, Ts...>
{ using type
= typename std::conditional<T::result,
typename T::type, typename funcType<Ts...>::type>::type; };
template <>
struct funcType<>
{ using type = emptyClass; };
#define methodCheck_1(meth) \
\
class helpMeth_1_##meth {}; \
\
template <typename T, typename A> \
struct isWithMethod_1_##meth \
{ \
template<typename U> \
static decltype(U().meth(A())) func (U*); \
\
template<typename U> \
static emptyClass func (...); \
\
static const bool result \
= ! std::is_same<emptyClass, \
decltype(func<T>(nullptr))>::value; \
\
using type = helpMeth_1_##meth; \
}
methodCheck_1(insert);
methodCheck_1(push);
methodCheck_1(push_back);
methodCheck_1(push_front);
template <typename>
class cntWrp;
template <template <typename ...> class C, typename X, typename ... Xs>
class cntWrp< C<X, Xs...> >
{
private:
using addModeType = typename funcType<
isWithMethod_1_push_back<C<X, Xs...>, X>,
isWithMethod_1_insert<C<X, Xs...>, X>,
isWithMethod_1_push<C<X, Xs...>, X>,
isWithMethod_1_push_front<C<X, Xs...>, X>>::type;
static constexpr addModeType addMode {};
void addVal (X const & x, helpMeth_1_push_back const)
{ val.push_back(x); }
void addVal (X const & x, helpMeth_1_push const)
{ val.push(x); }
void addVal (X const & x, helpMeth_1_insert const)
{ val.insert(x); }
void addVal (X const & x, helpMeth_1_push_front const)
{ val.push_front(x); }
void addVal (X const & x, emptyClass const)
{ throw std::runtime_error("cntWr<>::addVal without mode"); }
public:
C<X, Xs...> val {};
cntWrp ()
{ }
cntWrp (C<X, Xs...> const & v0) : val { v0 }
{ }
void addVal (X const & x)
{ addVal(x, addMode); }
};
int main ()
{
cntWrp<std::set<int>> csi;
csi.addVal(2);
csi.addVal(7);
csi.addVal(5);
std::cout << "set:" << std::endl;
for ( auto const elem : csi.val )
std::cout << elem << std::endl;
cntWrp<std::vector<int>> cvi;
cvi.addVal(2);
cvi.addVal(7);
cvi.addVal(5);
std::cout << "vector:" << std::endl;
for ( auto const elem : cvi.val )
std::cout << elem << std::endl;
}