首页 > 解决方案 > 带有 const 重载和模板的模棱两可的调用

问题描述

在我的图像类中,我使用以下 const 重载模板函数提供对特定行的直接内存访问

template <typename T>
inline T* Image::getRow(unsigned int y)
{
    ...
}

template <typename T>
inline const T* Image::getRow(unsigned int y) const
{
    ...
}

但是,如果我指定另一个实际使用这些模板的函数:

template <typename T>
void Image::compute(...)
{
    ...
    T* pImageRow = getRow<T>(y); //error C2668
    ...
}

我收到以下错误error C2668: 'Image::getRow': ambiguous call to overloaded function

有没有办法告诉编译器它实际上应该使用非常量变体Image::getRow

最小的例子

研究一个可重现的示例,我发现问题似乎更深一些(实际上,如果我getRow从 lambda 函数调用parallelFor):

最小的例子在这里:


inline void parallelFor(unsigned int endIndex, const std::function<void(unsigned int i)>& computeFunction, unsigned int startIdx = 0)
{
    #pragma omp parallel for
    for(int i = startIdx; i < (int)endIndex; i++)
    {
        computeFunction((unsigned int)i);
    }
}

class Image
{
public:
    template <typename T>
    T* getRow(unsigned int y);
    template <typename T>
    const T* getRow(unsigned int y) const;
    template <typename T>
    void compute(const std::function<void(unsigned int x, unsigned int y, T& data)>& computeFunction);
};

template <typename T>
inline T* Image::getRow(unsigned int y)
{
    return (T*)nullptr;
}

template <typename T>
inline const T* Image::getRow(unsigned int y) const
{
    return (const T*)nullptr;
}

template <typename T>
void Image::compute(const std::function<void(unsigned int x, unsigned int y, T& data)>& computeFunction)
{
    unsigned int rows = 10;
    unsigned int cols = 10;

    parallelFor(rows,
        [&](unsigned int y)
        {
            T* pImageRow = getRow<T>(y);
            for(unsigned int x = 0; x < cols; x++)
            {
                T& curVal = pImageRow[x];
                computeFunction(x, y, curVal);
            }
        });
}

int main(int argc, char** argv)
{
    Image a;
    a.compute<unsigned char>([](unsigned int x, unsigned int y, unsigned char& color) { color = 0; });

    return 0;
}

标签: c++templates

解决方案


添加constvoid Image::compute(...)

void Image::compute(...) const

如果这是不可能的,但 t 可以指向一个常量,那么做

template <typename T>
void Image::compute(...)
{
    ...
    const T* pImageRow = static_cast<const Image*>(this)->getRow<T>(y);
    ...
}

如果两者都不可能,则向其中一个重载参数添加第二个虚拟参数。


推荐阅读