使用以基数 class 作为参数的模板
Use template with base class as parameter
我想定义一个模板 class,其中包含针对不同类型的一些方法的专门化。
template <typename T>
class Handler {
public:
void method1() { method2(); }
protected:
void method2();
}
然后在实现文件中:
template <> Handler<int>::method2() { doSomething(); }
template <> Handler<float>::method2() { doSomethingElse(); }
template <> Handler<ClassB>::method2() { doSomethingDifferent(); }
到目前为止,一切正常。
现在我想定义一些从 ClassB 派生的新 classes,并对这些 classes 的对象使用模板特化。当然它编译但不编译 link,因为缺少每个子 class 的特化。
有没有办法使用这些模板,例如使用 SFINAE?
第一个:
template <class T,class=void>
class Handler
然后使用 SFINAE 创建专业:
template <class T>
class Handler<T,std::enable_if_t<test>>
现在,让该专业化在其主体中包含其实现,或者从实现类型(非模板)继承并在 impl 文件中实现它。
为了您的目的,测试可能是基础。
您的 int impl 现在需要添加一个 ,void
参数。
您还可以使用特征 class 进行条件映射。
我经常发现在类型标签上重载是专门化的一个很好的替代方法:
namespace {
template<class T> struct Type { using type = T; }; // Or boost::type<T>
template<class T> struct TypeTag { using type = Type<T>; };
struct ClassB {};
template <typename T>
class Handler {
public:
void method1() {
method2(typename TypeTag<T>::type{}); // Call an overloaded function.
}
protected:
void method2(Type<int>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
void method2(Type<float>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
void method2(Type<ClassB>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
// Somewhere else.
struct ClassC : ClassB {};
template<> struct TypeTag<ClassC> { using type = Type<ClassB>; };
} // namespace
int main(int ac, char**) {
Handler<ClassB> b;
b.method1();
Handler<ClassC> c;
c.method1();
}
输出:
void {anonymous}::Handler<T>::method2({anonymous}::Type<{anonymous}::ClassB>) [with T = {anonymous}::ClassB]
void {anonymous}::Handler<T>::method2({anonymous}::Type<{anonymous}::ClassB>) [with T = {anonymous}::ClassC]
我想定义一个模板 class,其中包含针对不同类型的一些方法的专门化。
template <typename T>
class Handler {
public:
void method1() { method2(); }
protected:
void method2();
}
然后在实现文件中:
template <> Handler<int>::method2() { doSomething(); }
template <> Handler<float>::method2() { doSomethingElse(); }
template <> Handler<ClassB>::method2() { doSomethingDifferent(); }
到目前为止,一切正常。
现在我想定义一些从 ClassB 派生的新 classes,并对这些 classes 的对象使用模板特化。当然它编译但不编译 link,因为缺少每个子 class 的特化。
有没有办法使用这些模板,例如使用 SFINAE?
第一个:
template <class T,class=void>
class Handler
然后使用 SFINAE 创建专业:
template <class T>
class Handler<T,std::enable_if_t<test>>
现在,让该专业化在其主体中包含其实现,或者从实现类型(非模板)继承并在 impl 文件中实现它。
为了您的目的,测试可能是基础。
您的 int impl 现在需要添加一个 ,void
参数。
您还可以使用特征 class 进行条件映射。
我经常发现在类型标签上重载是专门化的一个很好的替代方法:
namespace {
template<class T> struct Type { using type = T; }; // Or boost::type<T>
template<class T> struct TypeTag { using type = Type<T>; };
struct ClassB {};
template <typename T>
class Handler {
public:
void method1() {
method2(typename TypeTag<T>::type{}); // Call an overloaded function.
}
protected:
void method2(Type<int>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
void method2(Type<float>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
void method2(Type<ClassB>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
// Somewhere else.
struct ClassC : ClassB {};
template<> struct TypeTag<ClassC> { using type = Type<ClassB>; };
} // namespace
int main(int ac, char**) {
Handler<ClassB> b;
b.method1();
Handler<ClassC> c;
c.method1();
}
输出:
void {anonymous}::Handler<T>::method2({anonymous}::Type<{anonymous}::ClassB>) [with T = {anonymous}::ClassB]
void {anonymous}::Handler<T>::method2({anonymous}::Type<{anonymous}::ClassB>) [with T = {anonymous}::ClassC]