假设我想为2个或更多类编写一个包装器,它们使用不同的实现执行相同的操作,并且它们的接口具有不同的函数名称。根据上下文,我会选择其中一个,但我希望能够轻松地将它们切换出来。所以我写了一个包含模板特化的包装器。好的。但是现在我遇到了一个问题。我的2个类是模板类......
如果它们是正常的类,我可以编写这样的代码:
class A1
{
public:
int f()
{
return 1;
}
};
class A2
{
public:
int g()
{
return 1;
}
};
namespace detail
{
template <class T> int h(T& t) // general case
{
std::cout << "general" << "\n";
return t.h();
}
template <> int h<A1>(A1& a1) // case for A1
{
std::cout << "A1" << "\n";
return a1.f();
}
template <> int h<A2>(A2& a2) // case for A2
{
std::cout << "A2" << "\n";
return a2.g();
}
}
template <class T>
class Wrapper
{
public:
Wrapper(T& t) : t(t) {}
int operator()()
{
return detail::h<T>(t);
}
T& t;
};
但是,我如何修改该代码以使其针对A1
和A2
的有效版本运行?我想出的最好的是(不编译):
template <class T>
class A1
{
public:
int f()
{
return 1;
}
};
template <class T>
class A2
{
public:
int g()
{
return 1;
}
};
namespace detail
{
template <class T, class U> int h(T<U>& t) // general case
{
return t.h();
}
template <> int h<A1<U>>(A1<U>& a1) // case for A1
{
return a1.f();
}
template <> int h<A2<U>>(A2<U>& a1) // case for A2
{
return a1.f();
}
}
template <class T, class U>
class Wrapper
{
public:
Wrapper(T<U>& t) : t(t) {}
int operator()()
{
return detail::h<T,U>(t);
}
T<U>& t;
};
所以,我不知何故需要模板化模板专业化,这听起来像是一个矛盾。
好的..尝试让过载解决方案正常工作,但我真的不明白......
template <template <typename> class T, class U>
class Wrapper
{
public:
Wrapper(T<U>& t) : t(t) {}
template <template <typename> class T, typename U>
int h(T<U>& t) // general case
{
return t.h();
}
template <typename U>
int h(A1<U>& a1) // case for A1
{
return a1.f();
}
template <typename U>
int h(A2<U>& a2) // case for A2
{
return a2.g();
}
T<U>& t;
};
答案 0 :(得分:4)
首选模板专业化过载:
template <template <typename> class T, typename U>
int h(T<U>& t) // general case
{
return t.h();
}
template <typename T>
int h(A1<T>& a1) // case for A1
{
return a1.f();
}
template <typename T>
int h(A2<T>& a2) // case for A2
{
return a2.g();
}