我有一个包含大量功能的类Data。 该类还可能具有0或N个其他类型,这些类型是实现类功能所必需的:
// in Data.h
template <typename T, typename ...Args>
class Data
{
T f1();
T f2() const;
... // skipped
void f10(const T& v);
// Pimpl
struct Impl;
Impl* _imp;
};
然而,如果sizeof...(Args) == 0
和sizeof...(Args) > 0
,某些函数(但不是全部!)的实现完全不同:
主要是,内部私有实现类包含不同的类型。
// in DataImpl.h
template <typename T, typename ...Args>
struct ImplementationSpecificData;
template <typename T>
struct ImplementationSpecificData<T>
{
// Some members available when sizeof...(Args) == 0
};
template <typename T, typename ...Args>
struct ImplementationSpecificData<T, Args...>
{
// Some members available when sizeof...(Args) > 0
};
// The pimpl
template <typename T, typename ...Args>
struct Data<T,Args...>::Impl
{
// Some common members
...
// Following are specific whether sizeof...(Args) is > 0 or == 0
ImplementationSpecificData<T,Args...> specificData;
};
// In Data.cpp
#include "DataImpl.h"
然后,对于具有依赖于 specificData 的实现的函数,我想专门化这些函数,例如:
template <typename T, typename ...Args>
T
Data<T,Args...>::f1() {
// Case where sizeof...(Args) > 0
}
//以下内容无法正常工作,因为这是部分成员模板专业化
template <typename T>
T
Data<T>::f1() {
// Case where sizeof...(Args) == 0
}
我尝试使用额外的Enable模板boolean并专门化需要的函数
template <typename T, bool Enable, typename ...Args>
class Data
{
...
};
template <typename T, typename ...Args>
T
Data<T,
std::integral_constant<bool, sizeof...(Args) > 0>::value,
Args...>::f1() {
// Case where sizeof...(Args) > 0
}
template <typename T, typename ...Args>
T
Data<T,
std::integral_constant<bool, sizeof...(Args) == 0>::value,
Args...>::f1() {
// Case where sizeof...(Args) == 0
}
但这也不起作用,我得到以下结论:
声明的嵌套名称说明符Data<T, std::integral_constant<bool, (sizeof...(Args) > 0)>::value, Args...>::
不引用类,类模板或类模板部分特化
是否有一种优雅的方法来实现这一点,而不会使用包含纯虚函数的基类和没有其他类型的派生类D1以及带有其他类型的派生类D2来污染我的API: 这需要在所有这三个类(Base,D1和D2)中维护类的函数签名(并且有很多函数)。
答案 0 :(得分:1)
在您的实现中使用重载/标记分派:
template <typename T, typename ...Args>
T f1_impl(Data<T, Args...>&) {
// sizeof...(Args) > 0
}
template <typename T>
T f1_impl(Data<T>&) {
// sizeof...(Args) == 0
}
template <typename T, typename ...Args>
T Data<T, Args...>::f1() {
return f1_impl(*this);
}