const重载模板函数调用歧义问题:如何指定调用非const版本?
解决
Image::getRow重载调用歧义的问题 这个歧义问题的根源其实很好理解:C++的重载决议不考虑返回值类型,只看函数参数和调用对象的const属性。你的compute是非const成员函数,this指向的是一个非const的Image对象,但非const对象既可以调用非const版本的getRow,也可以调用const版本的getRow——两个重载的参数列表完全一致,编译器没法自动判断你要调用哪一个,所以就抛出了歧义错误。
下面给你几个实用的解决方案,按简洁程度排序:
方案1:用非const引用明确调用上下文
这是最简单的写法,在lambda外面把当前对象绑定到一个非const引用上,然后通过这个引用调用getRow,编译器就会明确选择非const版本:
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; // 绑定到非const引用,给编译器明确的调用上下文 Image& self = *this; parallelFor(rows, [&](unsigned int y) { T* pImageRow = self.getRow<T>(y); for(unsigned int x = 0; x < cols; x++) { T& curVal = pImageRow[x]; computeFunction(x, y, curVal); } }); }
方案2:显式指定非const成员函数指针
如果你想更直接地告诉编译器要调用哪个版本,可以显式获取非const版本的getRow成员函数指针,然后通过指针调用:
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; // 显式声明并赋值非const版本的成员函数指针 T* (Image::*getRowNonConst)(unsigned int) = &Image::getRow<T>; parallelFor(rows, [&](unsigned int y) { T* pImageRow = (this->*getRowNonConst)(y); for(unsigned int x = 0; x < cols; x++) { T& curVal = pImageRow[x]; computeFunction(x, y, curVal); } }); }
方案3:修改getRow接口(可选)
如果允许修改类的公共接口,可以给两个重载添加不同的默认参数来区分,让编译器自动匹配:
#include <type_traits> // 需要引入这个头文件 class Image { public: // 非const版本用std::false_type作为默认参数 template <typename T> T* getRow(unsigned int y, std::false_type = {}); // const版本用std::true_type作为默认参数 template <typename T> const T* getRow(unsigned int y, std::true_type = {}) const; }; // 实现部分 template <typename T> inline T* Image::getRow(unsigned int y, std::false_type) { return (T*)nullptr; } template <typename T> inline const T* Image::getRow(unsigned int y, std::true_type) const { return (const T*)nullptr; }
调用的时候不需要额外传参数,编译器会根据调用对象的const属性自动选择对应的版本,完美消除歧义。
内容的提问来源于stack exchange,提问作者RatTac
相关产品推荐
相关产品推荐

