【问题标题】:template partial specialization prevents initialization from derived class模板部分特化防止从派生类初始化
【发布时间】:2012-07-30 22:52:14
【问题描述】:

我从具有部分特化的模板继承,我不能从派生的 ctor 调用模板 ctor。

当下面代码中的部分特化被注释掉时,它编译时不会出现任何错误或警告。

#include <iostream>
typedef enum {supertype, subtype} selector;

template< typename T, selector s>
class Tmpl {
protected:
    T* root;
public:
    Tmpl( T* t = 0 ) {
        root = t;
    }
    T listHead( ) {
        std::cout << "template listHead() called" << std::endl;
    }
};

class Descriptor {
public:
    Descriptor( const char * s ) {
        std::cout << "Descriptor " << s << std::endl;
    }
};

// partial specialization - if uncommented, errors 
// are reported at the supertypesIterator ctor below.
/*
template<selector s>
class Tmpl<Descriptor, s> {
public:
    Descriptor listHead( ) {
        switch( s ){
            case supertype:
                return Descriptor("Supertypes");
            case subtype:
                return Descriptor("Subtypes");
        }
    }
};
*/

class supertypesIterator : public Tmpl<Descriptor, supertype> {
public:
    supertypesIterator( Descriptor* t = 0 ):Tmpl<Descriptor, supertype>(t) {}
};


main() {
    supertypesIterator s;
    s.listHead();
}

如果我取消注释专业化,我会收到以下错误:

$g++ trouble.cc

trouble.cc: In constructor ‘supertypesIterator::supertypesIterator(Descriptor*)’:
trouble.cc:43:74: error: no matching function for call to ‘Tmpl<Descriptor, (selector)0u>::Tmpl(Descriptor*&)’
trouble.cc:43:74: note: candidates are:
trouble.cc:27:7: note: Tmpl<Descriptor, (selector)0u>::Tmpl()
trouble.cc:27:7: note:   candidate expects 0 arguments, 1 provided
trouble.cc:27:7: note: Tmpl<Descriptor, (selector)0u>::Tmpl(const Tmpl<Descriptor, (selector)0u>&)
trouble.cc:27:7: note:   no known conversion for argument 1 from ‘Descriptor*’ to ‘const Tmpl<Descriptor, (selector)0u>&’

我需要做什么才能从supertypesIterator ctor 中初始化基类?

我使用的是 g++ 版本 4.7.1,不过我还需要它才能跨平台工作。

【问题讨论】:

    标签: c++ templates derived-class partial-specialization constructor-chaining


    【解决方案1】:

    您必须在您的专业化中实现缺少的构造函数。否则,supertypesIterator 的构造函数会尝试调用不存在的 Tmpl 的构造函数。

    template<selector s>
    class Tmpl<Descriptor, s> {
        Descriptor* root;
    public:
        Tmpl( Descriptor* t = 0 ) {
            root = t;
        }
        Descriptor listHead( ) {
            switch( s ){
                case supertype:
                    return Descriptor("Supertypes");
                case subtype:
                    return Descriptor("Subtypes");
            }
        }
    };
    

    【讨论】:

    • 啊哈!不久前,我尝试将 ctor Tmpl( Descriptor* t = 0 ): Tmpl(t) {} 添加到专业化中,但这不起作用(“警告:委托构造函数仅适用于...”)。你的版本确实有效。所以模板特化被处理类似于派生类......我认为他们不是。
    • @Mark:模板专业化是对您提供的一组参数的模板的重新实现。因此,如果有很多重叠,那就太可惜了,但它确实提供了充分的灵活性。
    • 好像没有办法从特化中的构造函数调用非特化构造函数?
    • 别管我的最后一个问题,我想我找到了答案here
    • @Mark:如果你想要代码重用,你必须创建一个抽象。例如,可以为容器创建模板特化,以便指针类型可以重用从void * 实例化的常规模板中的代码。格式很难看,但大体思路描述为here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 2010-11-10
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    相关资源
    最近更新 更多