优先考虑一个操作员[]而不是另一个操作员
Giving preference to one operator[] over another
考虑以下类:
class Test
{
public:
Test( char );
Test( int );
operator const char*();
int operator[]( unsigned int );
};
当我使用它时:
Test t;
Test& t2 = t[0];
我发现编译器错误,它无法确定要使用哪个操作员[]。MSVC和GCC均两者。不同的错误。但是同样的问题。
我知道发生了什么。它可以从int或char构建测试,并且可以使用 Test::operator[]
,也可以施放用于const char*并使用已构建的char*[]
。
我希望它更喜欢Test::operator[]
。
有没有办法指定这样的偏好?
更新:首先,我会同意下面的响应,没有任何语言功能可以让您指定转换的优先级。但是,就像下面发现的Juanchopanza一样 - 您可以通过进行一个转换不需要铸件而间接创建如此偏好,而是使另一个需要铸造。例如。unsigned int
作为operator[]
的参数无法正常工作,但是使用int
会。
无论如何,默认索引参数是未签名的 - 对于GCC和MSVC,因此将索引参数无符号会导致编译器更喜欢正确的操作员。
@konrad:关于内置类型的隐式转换。一般同意。但是在这种情况下我需要它。
没有。这种歧义就是为什么不建议自动转换为另一种类型(例如operator char*
)的原因。
您始终可以制作构造函数explicit
- 或者,正如John所指出的那样,省略了转换操作员。我通常建议您做所有这些事情,但是由于您的代码是一个玩具示例,因此很难说您的情况适合您。
也就是说,以下内容应起作用:
Test const& t2 = t.operator[](0);
(请注意添加的const
- 否则您将临时绑定到不起作用的非const引用。)
我之前已经实现了像您这样的容器类 - 完全有可能避免歧义问题,同时保持干净,直观的语法。
首先,您需要考虑constness。通常,const char* cast不会修改对象,因此使其成为const成员函数:
operator const char*() const;
另外,您的[]操作员正在返回int而不是int&,因此这可能也应该是const:
int operator[]( unsigned int ) const;
如果您想能够为索引元素(mytest [5] = 2)分配一个值,则将添加其他操作符函数(这不会替换上面的const版本 - 保持两者):
int& operator[](unsigned int);
接下来,您将需要接受不仅仅是unsigned int的索引。字面整数具有INT类型。为了避免与索引类型相关的问题,您需要超载操作员的替代方案。这些过载只会static_cast到您的本机索引类型的索引,并将其传递给本机超载(用于本机索引类型的索引)。这些过载之一可能看起来像:
int operator[]( int idx ) const {
return operator[]( static_cast<unsigned int>(idx) );
}
您可以使用单个模板成员功能来涵盖所有可能性,而不是添加一堆过载。模板函数将用于任何尚未具有非网板过载的索引类型。对非板块过载的这种偏好是明确的。从本质上讲,这实现了您对首选操作员的请求,但是const-ness不能模板,因此,如果您有const和non-const []运算符,则需要两个版本。此捕获的所有成员功能可能看起来像这样(请记住,其定义必须留在您的班级声明中,并且不能移动到实现文件):
template <typename IT>
int operator[]( const IT& idx ) const {
return operator[]( static_cast<unsigned int>(idx) );
}
如果您添加了[]运算符的非const版本,则您也需要:
template <typename IT>
int& operator[]( const IT& idx ) {
return operator[]( static_cast<unsigned int>(idx) );
}
享受!
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 运行同一解决方案的另一个项目的项目
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- C++从另一个类访问公共静态向量的正确方法是什么
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- 使用std::transform将一个范围的元素添加到另一个范围中
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- 修改函数中的指针(将另一个指针作为参数传递)
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- C++试图读取一个文件并输出到另一个文本文件
- 如何将指针从一个void函数传递到另一个C++
- 如何从另一个文件继承私有成员变量和公共函数
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 使用超载操作员可以实现另一个操作员超载
- OpenCV:文件存储操作员">>"在一个项目中工作,但不在另一个项目中工作(在同一类上)
- 使用##预处理器操作员与另一个宏输出
- 优先考虑一个操作员[]而不是另一个操作员