是否可以定义std::array的隐式转换运算符? 我尝试有一个C++类,可以隐式转换为 STD::转换是有效的,但不是隐式的 #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; }
当然,这意味着失去了std::array的许多细节,如果没有更好的解决方案,我会接受。你可以通过在是否可以定义std::array的隐式转换运算符? 我尝试有一个C++类,可以隐式转换为 STD::转换是有效的,但不是隐式的 #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; },c++,c++11,implicit-conversion,C++,C++11,Implicit Conversion,当然,这意味着失去了std::array的许多细节,如果没有更好的解决方案,我会接受。你可以通过在a上重载操作符[]和begin(),或者公开继承array(不推荐) 隐式转换只有在有意义时才起作用(例如,如果您将A传递给一个需要std::array的函数),而不是在您的情况下。如果你问我这是件好事。我是通过评论回答你的问题的: 你能解释一下为什么我的转换没有意义吗?当试图解析运算符[]时,编译器为什么不考虑可能的转换? 简短的回答,因为这就是它的工作原理。这里可以调用到内置类型的转换运算符,而
a
上重载操作符[]
和begin()
,或者公开继承array
(不推荐)
隐式转换只有在有意义时才起作用(例如,如果您将
A
传递给一个需要std::array
的函数),而不是在您的情况下。如果你问我这是件好事。我是通过评论回答你的问题的:
你能解释一下为什么我的转换没有意义吗?当试图解析运算符[]时,编译器为什么不考虑可能的转换? 简短的回答,因为这就是它的工作原理。这里可以调用到内置类型的转换运算符,而不是到用户定义类型的转换运算符 再长一点回答: 在表达式中使用运算符时,重载解析将遵循
13.3.1.2
中列出的规则
第一:
2如果任一操作数的类型为类或枚举,则可能需要用户定义的运算符函数
声明实现此运算符或转换操作数可能需要用户定义的转换
适用于内置运算符的类型。在这种情况下,过载分辨率用于确定
要调用哪个运算符函数或内置运算符来实现运算符[…]
为此,a[1]
被解释为a.operator[](1)
,如同一节中的表11所示
然后按如下方式执行查找:
3对于cv不合格版本为T1的操作数类型的一元运算符@,以及二进制运算符
运算符@,其cv不合格版本为T1的类型的左操作数和类型的右操作数
其简历不合格版本为T2,三套候选人职能,指定成员候选人,非-
成员候选者和内置候选者的构造如下:
-如果T1是一个完整的类类型,则成员候选集是
T1::操作员@(13.3.1.1.1);否则,成员候选集为空[1]
-非成员候选集是上下文中运算符@不合格查找的结果
根据非限定函数调用中名称查找的常用规则(3.4.2)对表达式进行排序
除了忽略所有成员函数之外。但是,如果没有操作数具有类类型,则只有
查找集中第一个参数类型为T1或“参考(可能)”的非成员函数
cv限定)T1“,当T1是枚举类型,或(如果有右操作数)第二个参数时
当T2为枚举类型时,T2类型或“参考(可能符合cv)T2”类型为候选
功能[2]
-对于运算符、、一元运算符和或运算符->,内置候选集为空。
对于所有其他操作符,内置候选操作符包括所有定义的候选操作符函数
在13.6中,与给定的运算符相比
-具有相同的操作员名称,并且
-接受相同数目的操作数,并且
-接受给定操作数可根据其转换为的操作数类型
13.3.3.1和[3]
-不具有与任何非模板非成员候选项相同的参数类型列表
结果如下:
[1]
找不到任何内容(您的类中没有运算符[]
)
[2]
什么也找不到(没有自由函数运算符[]
,两个操作数都不是枚举类型)
[3]
查找内置的运算符[](float*,std::ptrdiff\u t)
,因为A
声明转换为float*
你能详细说明为什么我的转换没有意义吗?当试图解决<代码>运算符[]/COD>时,编译器为什么不考虑可能的转换?引证,这似乎是第二种情况:当某种类型的表达式在不接受该类型的上下文中使用,但接受另一种类型的表达式时,会执行隐式转换,特别是:[…]当该表达式被用作操作数时,运算符应为T2
@kccqzy您的begin
示例比该语句稍微复杂一点,它是一个额外的步骤,用于遍历所有转换运算符以查看哪些运算符匹配..以及如果多个运算符匹配该怎么办。[]
case非常感谢。这正是我要找的。一个侧面的评论:根据我的n3092.pdf副本,该表应该是表10
,而不是表11
?@kccqzy我使用了n3337,它们很可能不同。你的例子确实毫无意义:只是公开继承自std::array解决了您的所有问题。为什么您希望允许隐式转换到成员的类型而不是从该类型继承?该示例没有意义,因为这是一个过于简化的版本。但您不能简单地宣称隐式转换到std::array
的想法仅仅从如果我希望允许隐式转换,不是到成员,而是到可能动态构造并存储在堆上的其他对象,该怎么办?如果隐式转换器有自己的
operator float *() { return data.begin(); }
operator const float *() const { return data.cbegin(); }