[英]Is it possible to define an implicit conversion operator to std::array?
我试图有一个可以隐式转换为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
的许多细节,如果没有更好的解决方案,我会接受。
您可以通过在A
上重载operator[]
和begin()
,或者从array
公开继承(不推荐)来使它们工作。
隐式转换仅在有意义时才会起作用(例如,如果您将A
传递给期望std::array<float, 7>
的函数),而不是在您的情况下。 如果你问我,这是件好事。
我正在评论中回答你的问题:
你能详细说明为什么我的转换没有意义吗? 在尝试解析operator []时,为什么编译器不考虑可能的转换?
简短的回答,因为它是如何工作的。 可以在此处调用内置类型的转换运算符,而不是用户定义的类型。
更长的答案:
在表达式中使用运算符时,重载解析遵循13.3.1.2
规定的规则。
第一:
2如果任一操作数具有类或枚举类型,则可以声明用户定义的操作符函数来实现此操作符,或者可能需要用户定义的转换将操作数转换为适合构建的类型-in运算符。 在这种情况下,重载决策用于确定调用哪个运算符函数或内置运算符来实现运算符[...]。
为此, a[1]
被解释为a.operator[](1)
,如同一部分的Table 11
所示。
然后按如下方式执行查找:
3对于具有cv-unquali fi ed版本为T1的类型的操作数的一元运算符@,以及具有cv-unquali fi ed版本为T1的类型的左操作数的二元运算符@和具有cv-的类型的右操作数的二元运算符@ unquali fi ed版本为T2,三组候选函数,指定成员候选者,非成员候选者和内置候选者,构造如下:
- 如果T1是一个完整的类类型,则候选成员集合是T1 :: operator @(13.3.1.1.1)的限定查找结果; 否则,成员候选人是空的。 [1]
- 非成员候选集合是根据通常的非标准函数调用(3.4.2)中的名称查找规则在表达式上下文中对operator @进行不等式查找的结果,除了忽略所有成员函数。 但是,如果没有操作数具有类类型,则只有查找集中具有类型T1的第一个参数或“引用(可能是cv-quali fi ed)T1”的非成员函数,当T1是枚举类型时,或者(如果存在右操作数)T2类型的第二个参数或“引用(可能是cv-quali fi ed)T2”,当T2是枚举类型时,是候选函数。 [2]
- 对于运算符,一元运算符&或运算符 - >,内置候选集是空的。 对于所有其他运算符,内置候选项包括13.6中定义的所有候选运算符函数,与给定运算符相比,
- 具有相同的运营商名称,和
- 接受相同数量的操作数,和
- 接受根据13.3.3.1和[3]可以转换给定操作数或操作数的操作数类型
- 没有与任何非模板非成员候选者相同的参数类型列表。
结果如下:
[1]
找不到任何东西(你班上没有operator[]
[2]
什么都没找到(没有自由函数operator[]
并且两个操作数都不是枚举类型) [3]
找到内置的operator[](float*, std::ptrdiff_t)
因为A
声明转换为float*
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.