我正在尝试使用可以隐式转换为std::array
的C ++类。转换有效,但并非隐含。
#include <array>
class A {
private:
std::array<float, 7> data;
public:
operator std::array<float, 7>&() { return data; }
operator const std::array<float, 7>&() const { return data; }
};
int main() {
A a;
a[1] = 0.5f; // fails to compile
auto it = a.begin(); // fails to compile
A b;
static_cast<std::array<float, 7>>(b)[1] = 0.5f; //ok
auto it2 = static_cast<std::array<float, 7>>(b).begin(); //ok
return 0;
}
我理解上面的例子很复杂,因为它基本上完全暴露了类的private
成员。但这是一个过于简单的例子,我只是想解决为什么隐含转换到std::array
不起作用的问题。
我已经使用clang-3.2
和gcc-4.8
尝试了上述示例。都没有编译。
更令人困惑的是,如果我使用隐式转换到指针,编译显然会成功:
operator float *() { return data.begin(); }
operator const float *() const { return data.cbegin(); }
但当然,这意味着失去std::array
的许多细节,如果没有更好的解决方案,我会接受。
答案 0 :(得分:3)
您可以通过在operator[]
上重载begin()
和A
,或者从array
公开继承(不推荐)来让他们工作。
隐式转换仅在有意义时才会起作用(例如,如果您将A
传递给期望std::array<float, 7>
的函数),而不是在您的情况下。如果你问我,这是件好事。
答案 1 :(得分:3)
我正在通过评论回答你的问题:
请您详细说明为什么我的转换没有意义?在尝试解析operator []时,为什么编译器不考虑可能的转换?
简短的回答,因为它是如何运作的。可以在此处调用内置类型的转换运算符,而不是用户定义的类型。
更长的答案:
在表达式中使用运算符时,重载决策遵循13.3.1.2
中规定的规则。
首先:
为此目的,2如果任一操作数的类型是类或枚举,则用户定义的操作符函数可能是 声明实现此运算符或用户定义的转换可能是转换操作数所必需的 到适合内置运算符的类型。在这种情况下,使用重载决策来确定 调用哪个运算符函数或内置运算符来实现运算符[...]。
a[1]
被解释为a.operator[](1)
,如同一部分的Table 11
所示。
然后按如下方式执行查找:
3对于带有cv-unquali fi ed版本为T1的类型的操作数的一元运算符@和对于二进制运算符 operator @,左侧操作数的类型,其cv-unquali fi ed版本为T1,右操作数为类型 其cv-unquali fi ed版本为T2,三组候选函数,指定成员候选者,非 成员候选人和内置候选人的构建如下:
- 如果T1是一个完整的类类型,那么候选成员集就是合格查找的结果 T1 :: operator @(13.3.1.1.1);否则,成员候选人是空的。的 [1] 强>
- 非成员候选者集合是在上下文中对operator @进行不等式查找的结果 根据通常的不合格函数调用中的名称查找规则的表达式(3.4.2) 除了忽略所有成员函数。但是,如果没有操作数具有类类型,则只有那些类型 查找集中具有第一个T1类型参数或“引用(可能是)的非成员函数 cv-quali fi ed)T1“,T1是枚举类型,或者(如果有右操作数)第二个参数 类型T2或“引用(可能是cv-quali fi ed)T2”,当T2是枚举类型时,是候选 功能。 [2]
- 对于运营商,一元运算符&amp;或运算符 - >,内置候选集是空的。 对于所有其他运算符,内置候选项包括所有已定义的候选运算符函数 在13.6中,与给定的算子相比,
- 具有相同的运营商名称和
- 接受相同数量的操作数,和
- 接受可根据要转换给定操作数或操作数的操作数类型 13.3.3.1和 [3]
- 与任何非模板非成员候选者没有相同的参数类型列表。
结果如下:
[1]
找不到任何内容(您班级中没有operator[]
[2]
什么都没找到(没有自由函数operator[]
,而且两个操作数都不是枚举类型)[3]
找到内置operator[](float*, std::ptrdiff_t)
,因为A
声明转换为float*