如何确定从类模板继承的模板参数的基础模板类型?

时间:2016-07-27 13:48:01

标签: c++ templates

之前可能已经提出并回答了这个问题,但我还没有找到搜索条件来找到它。这里有一些代码来显示我的问题(打算作为伪代码......如果需要请求澄清)。

image.h的:

template <class T>
class Image
{
    public:
        // Return pointer to data.
        T* GetValues(); 

        std::vector<T> data_;

};

template <class T>
T* Image<T>::GetValues()
{
    return &data_[0];
}

SpecialImage.h

class SpecialImage : public Image<float>
{

}

Stack.h

template<class T>
class Stack
{
    public:

        void NegateAllImageValues();

        std::vector<T> stackOfImages_;
};

template <class T>
void Stack::NegateAllImageValues()
{
    for(int i = 0; i < stackOfImages_.size(); ++i)
    {
        // Type L should be float if T=SpecialImage, but how to get?
        L* imageValues = stackOfImages_.at(i).GetValues(); 

        // Loop over values and multiply by -1.0.
    }
}

的main.cpp

{
    // Create stack of SpecialImages.
    Stack<SpecialImage> myStack; 

    // Create special image and add some data.
    SpecialImage mySpecialImage; 
    mySpecialImage.data_.push_back(1.0f);
    mySpecialImage.data_.push_back(2.0f);
    mySpecialImage.data_.push_back(3.0f);

    // Add special image to stack.
    myStack.stackOfImages_.push_back(mySpecialImage);

    // Negate all values in all SpecialImages in the stack.
    myStack.NegateAllImageValues();

}

我的问题是如何知道Stack :: NegateAllImageValues中的类型L?我意识到我可以写一个方法Image :: NegateAllValues并从Stack :: NegateAllImageValues调用它,但我想知道是否有办法在Stack级别获得类型L.我想我可以在函数Stack :: NegateAllImageValues中添加一个额外的模板参数,如

template <class T, class L>
void Stack::NegateAllImageValues()
{
    for(int i = 0; i < stackOfImages_.size(); ++i)
    {
        // Type L should be float if T=SpecialImage, but how to get?
        L* imageValues = stackOfImages_.at(i).GetValues(); 

        // Loop over values and multiply by -1.0.
    }
}

但是L类型不会被强制匹配Image的底层模板类型。

这里存在固有的设计缺陷吗?有没有办法在堆栈级别获取类型L?

1 个答案:

答案 0 :(得分:3)

这样做的经典方法是在Image类中添加typedef / alias,类似

template <typename T>
class Image {
public:
    typedef T value_type;

    // Other stuff
};

然后在您的Stack::NegateAllImageValues()方法中,您可以说

template <class T>
void Stack::NegateAllImageValues()
{
    for(int i = 0; i < stackOfImages_.size(); ++i)
    {
        typename T::value_type* imageValues = stackOfImages_.at(i).GetValues(); 

        // Loop over values and multiply by -1.0.
    }
}

这些typedef基本上由标准库中的每个模板类使用:例如,std::vector<T>包含(以及其他)成员typedef value_type,它是T的别名

C ++ 11及更新版本中的替代方法是使用auto代替,例如:

template <class T>
void Stack::NegateAllImageValues()
{
    for(int i = 0; i < stackOfImages_.size(); ++i)
    {
        auto* imageValues = stackOfImages_.at(i).GetValues(); 

        // Loop over values and multiply by -1.0.
    }
}

[普通autoauto*一样有效,但我更喜欢后者,因为它表明您期待指针类型。]

最后,在C ++ 11中,您可以使用decltype获取GetValues()的返回类型:

template <class T>
void Stack::NegateAllImageValues()
{
    for(int i = 0; i < stackOfImages_.size(); ++i)
    {
        using value_type = decltype(stackOfImages_.at(i).GetValues());
        value_type imageValues = stackOfImages_.at(i).GetValues(); 

        // Loop over values and multiply by -1.0.
    }
}

虽然这并没有让你获得auto以上的任何东西。