如何让内模板类成为外模板类的类型?

时间:2016-06-21 12:28:05

标签: c++ class templates inheritance nested

我目前的代码如下:Code here

我有一个模板ClassOuter和一个嵌套模板ClassInnerBase,其中TypeD可以是任何类型的TypeA, TypeB, TypeC而不是其他类型。此外,ClassInnerDerived应继承ClassInnerBase并实施virtual const int Method(int id) = 0;

template<typename TypeA, typename TypeB, typename TypeC>
class ClassOuter {
public:

    class ClassInnerBase {
    public:
        ClassInnerBase(int x) :
                m_x(x) {
        }

        virtual const int Method(int id) = 0;

    private:
        int m_x;
    };

    template<typename TypeD>
    class ClassInnerDerived : public ClassInnerBase {
    public:
        ClassInnerDerived<TypeD>(const TypeD &object, int x) :
                ClassInnerBase(x), m_object(object) {

        }

        // Implementation of ClassInnerBase::Method for type float
        template<>
        const int ClassInnerDerived<float>::Method(int id){
            return GetLookupID(id);
        }

        // Implementation of ClassInnerBase::Method for type double
        template<>
        const int ClassInnerDerived<double>::Method(int id){
            return GetLookupID(id);
        }


    private:
        TypeD m_object;
    };

    void DoSomething(const std::vector<ClassInnerBase> &inner_vec, int id);

    const int GetLookupID(int id) const{
        return lookup[id];
    }

private:
    int lookup[100];
};

template<typename TypeA, typename TypeB, typename TypeC>
void ClassOuter<TypeA, TypeB, TypeC>::DoSomething(const std::vector<ClassInnerBase> &inner_vec, int id){
    for(const auto &inner : inner_vec){
        inner.Method(id);
    }
}


int main()
{
    std::vector<typename ClassOuter<int, double, float>::ClassInnerBase> class_base_objects;
    typename ClassOuter<int, double, float>::template ClassInnerDerived<float> class_inner_derived_object(0.2f, 1);
    class_base_objects.push_back(class_inner_derived_object);

    typename ClassOuter<int, double, float>::template DoSomething(class_base_objects, 1);
}

我最终收到错误:

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:30:18: error: explicit specialization in non-namespace scope 'class ClassOuter<TypeA, TypeB, TypeC>::ClassInnerDerived<TypeD>'
         template<>
                  ^

我非常困在这里,不知道如何解决这个错误。 另外,如果有自己的实施,是否有任何建议/意见/改进?

1 个答案:

答案 0 :(得分:0)

正如您的编译器所说,您无法显式(完全)专门化模板类的内部类。当你试图从内部类中专门化一个方法时,你所做的更糟糕,即使对于非嵌套模板类也是如此......你可以做的是通过添加带有默认值的附加模板参数来欺骗编译器到你的内部阶级并部分地专注于整个内部阶级。这实际上可以让你使用sfinae机制来测试模板参数是否属于给定类型(如果内部模板参数实际上是双重或浮动的话,我在你的例子中进行了测试,但你可以类似地测试它是否是外部模板类型之一同样)例如:

#include <iostream>
#include <type_traits>
#include <vector>

template<typename TypeA, typename TypeB, typename TypeC>
class ClassOuter {
public:

    class ClassInnerBase {
    public:
        ClassInnerBase(int x) :
                m_x(x) {
        }

        virtual const int Method(int id) = 0;

    private:
        int m_x;
    };

    template<typename TypeD, typename = void>
    class ClassInnerDerived;

    template<typename TypeD>
    class ClassInnerDerived<TypeD, std::enable_if_t<std::is_same<TypeD, float>::value || std::is_same<TypeD, double>::value> >: public ClassInnerBase {
    public:
        // Implementation of ClassInnerBase::Method for type float
        ClassInnerDerived(const TypeD &object, int x) :
                ClassInnerBase(x), m_object(object) {
        }
        const int Method(int id){
            return GetLookupID(id);
        }
    private:
        TypeD m_object;
    };

    public:

    //static void DoSomething(const std::vector<ClassInnerBase> &inner_vec, int id);

    static const int GetLookupID(int id) {
        return lookup[id];
    }

private:
    static int lookup[100];
};

template<typename TypeA, typename TypeB, typename TypeC>
int ClassOuter<TypeA, TypeB, TypeC>::lookup[100];

/*
template<typename TypeA, typename TypeB, typename TypeC>
void ClassOuter<TypeA, TypeB, TypeC>::DoSomething(const std::vector<ClassInnerBase> &inner_vec, int id){
    for(const auto &inner : inner_vec){
        inner.Method(id);
    }
}*/


int main()
{
std::vector<typename ClassOuter<int, double, float>::ClassInnerBase *> class_base_objects;
    //typename ClassOuter<int, double, float>::template ClassInnerDerived<float> class_inner_derived_object(0.2f, 1);
    class_base_objects.push_back(new ClassOuter<int, double, float>::ClassInnerDerived<float>(0.2f, 1)); //(class_inner_derived_object);

    //typename ClassOuter<int, double, float>::template DoSomething(class_base_objects, 1);
}

上面的代码可能实际上并不是你想要的,但我认为这是一个很好的起点...