Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用以基类为参数的模板_C++_Templates_Sfinae - Fatal编程技术网

C++ 使用以基类为参数的模板

C++ 使用以基类为参数的模板,c++,templates,sfinae,C++,Templates,Sfinae,我想定义一个模板类,为不同的类型专门化一些方法 template <typename T> class Handler { public: void method1() { method2(); } protected: void method2(); } 模板 类处理程序{ 公众: void method1(){method2();} 受保护的: void方法2(); } 然后在实现文件中: template <> Handler<int>

我想定义一个模板类,为不同的类型专门化一些方法

template <typename T>
class Handler {
public:
    void method1() { method2(); }
protected:
    void method2();
}
模板
类处理程序{
公众:
void method1(){method2();}
受保护的:
void方法2();
}
然后在实现文件中:

template <> Handler<int>::method2() { doSomething(); }
template <> Handler<float>::method2() { doSomethingElse(); }
template <> Handler<ClassB>::method2() { doSomethingDifferent(); }
模板处理程序::method2(){doSomething();}
模板处理程序::method2(){doSomethingElse();}
模板处理程序::method2(){doSomethingDifferent();}
到目前为止,一切正常

现在我想定义一些从ClassB派生的新类,并在这些类的对象上使用模板专门化。当然,它会编译,但不会链接,因为缺少每个子类的专门化

是否有方法使用这些模板,例如使用SFINAE?

首先:

template <class T,class=void>
class Handler
模板
类处理程序
然后使用SFINAE创建专门化:

template <class T>
class Handler<T,std::enable_if_t<test>>
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();
}
模板
类处理程序
现在,让该专门化在其主体中包含其实现,或者从实现类型(非模板)继承并在impl文件中实现

对于你的钱包来说,测试可能是你成功的基础

您的int impl现在需要添加一个
,void
参数


您还可以使用traits类进行条件映射。

我经常发现类型标记上的重载是专门化的一个很好的替代:

template <class T>
class Handler<T,std::enable_if_t<test>>
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();
}
名称空间{
模板结构类型{using Type=T;};//或boost::Type
模板结构类型标记{using type=type;};
结构类B{};
模板
类处理程序{
公众:
void method1(){
method2(typename-TypeTag::type{});//调用重载函数。
}
受保护的:
void method2(Type){std::printf(“%s\n”,uu PRETTY_FUNCTION_uuu)}
void method2(Type){std::printf(“%s\n”,uu PRETTY_FUNCTION_uuu)}
void method2(Type){std::printf(“%s\n”,uu PRETTY_FUNCTION_uuu)}
};
//在别的地方。
结构ClassC:ClassB{};
模板结构类型标记{using type=type;};
}//名称空间
int main(int ac,字符**){
处理程序b;
b、 方法1();
处理程序c;
c、 方法1();
}
产出:

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]
void{anonymous}::Handler::method2({anonymous}::Type)[with T={anonymous}::ClassB]
void{anonymous}::Handler::method2({anonymous}::Type)[with T={anonymous}::ClassC]

您可以在头文件中包含模板代码-这可能不是您想要的,因为模板专门化在概念上不同于继承。如果模板中的成员函数未定义,则不能期望它像这样工作。你在找什么?如果没有,请更清楚地说明您试图实现的目标。我将尝试一下。这看起来像是使用附加间接级别的经典解决方案。@GB是的,您的观察非常准确。另一种方法是将所有类型映射到几个特定类别
TypeTag
将type
T
映射到category
TypeTag::type
。专门化
TypeTag
允许为任何类型定义类别。