【问题标题】:How to get inner template class to be of type of outer template class?如何让内部模板类成为外部模板类的类型?
【发布时间】:2016-10-23 00:05:39
【问题描述】:

我当前的代码如下所示: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<>
                  ^

我被困在这里,不知道如何解决这个错误。 另外,ifself 的实现有什么建议/cmets/改进吗?

【问题讨论】:

  • 您最好在Code Review 上更好地改进您的实施
  • @Rakete1111 不,代码审查不是用于存放损坏代码的地方,因为它在那边是题外话。他在正确的网站上问了。
  • @syb0rg 我只指改进位。对于实际错误,OP 在正确的站点上

标签: c++ class templates inheritance nested


【解决方案1】:

正如您的编译器所说,您不能显式(完全)专门化模板类的内部类。您正在做的甚至更糟,因为您试图从内部类中专门化一个方法,即使对于非嵌套模板类也是不可能的......您可以做的是通过添加具有默认值的附加模板参数来欺骗编译器到您的内部班级并部分专门化整个内部班级。这实际上将让您使用 sfinae 机制测试模板参数是否属于给定类型(我在您的示例中测试了内部模板参数是否字面上是 double 或 float 但您可以类似地测试它是否是外部模板类型之一以及)例如:

#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);
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    • 2011-10-08
    • 2018-11-28
    • 1970-01-01
    相关资源
    最近更新 更多