我有2个现有的类A和B.我想实现第三个结构C,这样C实现operator(),它将使用A或的任何容器使用不同的实现任何B的容器是否可以使用模板专业化来做这样的事情?
答案 0 :(得分:3)
enable_if
在很多场景中非常有用,但在这种情况下,我通常更倾向于使用标签调度。在我看来,代码看起来更干净,行为更可预测,如果你试图错误地使用它,错误消息会更有意义。
struct C
{
template <class T>
void operator()(const T& container) const
{
operator()(container, Tag<typename T::value_type>());
}
private:
template <class V> struct Tag {};
template <class T>
void operator()(const T& container, Tag<A>) const
{
std::cout << "A\n";
}
template <class T>
void operator()(const T& container, Tag<B>) const
{
std::cout << "B\n";
}
};
int main()
{
std::vector<A> a;
std::list<B> b;
C c;
c(a);
c(b);
}
答案 1 :(得分:2)
您可以使用模板模板参数执行此操作。
假设您的容器有两个参数(内容类型和分配器):
class A {};
class B {};
struct C {
template <
template <
typename,
typename
>
class V
>
void operator()(const V<A, std::allocator<A> >& /* ca */) const {
}
template <
template <
typename,
typename
>
class V
>
void operator()(const V<B, std::allocator<B> >& /* cb */) const {
}
};
然后,您可以执行以下操作:
int main() {
std::vector<A> va;
std::vector<B> vb;
std::list<A> la;
std::list<B> lb;
C c;
c(va);
c(la);
c(vb);
c(lb);
}
答案 2 :(得分:1)
是的,应该是可能的。 Arkanosis有一个很好的解决方案,但如果你想使用模板专业化,这就是:
class A {};
class B {};
template <template <typename , typename > class Z, class Elem> struct C
{
void operator()(const Z<Elem, std::allocator<Elem>>& v) { std::cout << "General implement" << std::endl; }
};
template <template <typename, typename > class Z> struct C<Z,B>
{
void operator()(const Z<B, std::allocator<B>>& v) { std::cout << "Specialized implement" << std::endl; }
};
然后是一些客户端代码:
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char** argv)
{
std::vector<A> as;
std::list<B> bs;
C<vector,A> ca;
ca(as);
C<list,B> cb;
cb(bs);
}
如果要处理来自同一C
- 样式类的不同容器类型,可以从C结构的模板派生,例如: class MultiContainerHandlerForA : public C<vector,A>, public C<list,A>
。
答案 3 :(得分:1)
使用std::enable_if
和std::is_same
的重载似乎有效。虽然不是很漂亮。请注意,这些是c ++ 11功能。
struct A {};
struct B {};
struct C {
template<class Cont>
void operator()(const Cont& c, typename std::enable_if<std::is_same<typename Cont::value_type, A>::value>::type * = NULL) const {
std::cout << "a";
}
template<class Cont>
void operator()(const Cont& c, typename std::enable_if<std::is_same<typename Cont::value_type, B>::value>::type * = NULL) const {
std::cout << "b";
}
};
int main() {
std::vector<A> a;
std::list<B> b;
C c;
c(a);
c(b);
}