在A或B的任何容器上重载模板成员函数
Overload template member function over any container of A or B
我有两个现有的类A和B。我想实现第三个结构C,这样C实现operator(),它将使用不同的实现来获取A的任何容器或的任何容器。使用模板专用化可以做这样的事情吗?
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 << "An";
}
template <class T>
void operator()(const T& container, Tag<B>) const
{
std::cout << "Bn";
}
};
int main()
{
std::vector<A> a;
std::list<B> b;
C c;
c(a);
c(b);
}
您可以使用模板模板参数来完成此操作。
假设您的容器有两个参数(内容类型和分配器):
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);
}
使用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);
}
是的,这应该是可能的。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>
。
相关文章:
- C++ 中重载成员函数的问题
- 如何将重载成员函数作为参数传递?
- 在 GDB - C++ 中反汇编重载成员函数
- 重载'->'成员访问运算符
- 非虚拟重载成员函数
- 重载成员函数的成员函数指针
- 重载成员选择运算符
- 找不到 VS2010 重载成员函数
- 将重载+成员函数的结果发送到重载<<导致编译错误
- 在"着色器程序"中找不到 C++ 重载成员函数
- 为什么不从线程调用重载成员
- C++ 解释重载成员函数迭代器(int i = 0) 的构造"one liner":i(i) { };
- C++强制mem_fun选择一个特定的重载成员函数
- 具有重载成员函数的多线程处理
- 消除作为模板参数传递的重载成员函数指针的歧义
- 指向常量重载成员函数的指针
- 带有重载成员函数的C++std::mem_fn
- 如何在设计API时设计带有const和volatile的重载成员函数
- 递归重载"->"(成员访问)
- 重载成员函数访问元组和递归累加结果失败的原因