Vor einiger Zeit habe ich etwas ähnliches für ein Projekt von mir entwickelt.
Ich habe ein voll funktionierendes Beispiel (der ursprüngliche Code ist komplexer) extrahiert zu zeigen, wie ein Verfahren verwenden addVal()
(diesen Anruf push_back()
, push()
, insert()
oder push_front()
) einen Wert in den Behälter eingewickelt hinzuzufügen.
Dieser Code funktioniert (wenn ich mich richtig erinnere) für std::vector
, std::set
, std::multiset
, std::unordered_set
, std::unordered_multiset
, std::deque
, std::queue
, std::priority_queue
, std::forward_list
und std::stack
.
Andere Behälter (z. B.-10) erfordern möglicherweise andere Spezialisierungen für cntWrp
.
Ich möchte nicht jede einzelne Codezeile erklären, aber wenn Sie Fragen haben, kann ich versuchen zu antworten (oder, wenn Sie es vorziehen, kann ich Ihnen den Link von meinem Github-Projekt geben).
Das Beispiel
#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;
}
Bezüglich der Standardcontainer, werden sie vererbt werden nicht ausgelegt ist. –
"Vererbung wird oft sogar von erfahrenen Entwicklern überstrapaziert." –
Da jeder 'ContainerWrapper' ein nicht verwandter Typ ist, warum willst du das? Ich meine, nicht jeder Std-Container kann "resized" werden. Was passiert, wenn ein "std :: set" übergeben wird, und wie macht das Ihre Lösung besser als nur "std :: set"? Sind Sie süchtig nach Dingen, die Mitglieder eines Typs sind? Warum nicht nur freie Funktionen? Wie 'sort (container)'. – Yakk