是否可以定义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的隐式转换运算符? 我尝试有一个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的函数),而不是在您的情况下。如果你问我这是件好事。我是通过评论回答你的问题的: 你能解释一下为什么我的转换没有意义吗?当试图解析运算符[]时,编译器为什么不考虑可能的转换? 简短的回答,因为这就是它的工作原理。这里可以调用到内置类型的转换运算符,而

当然,这意味着失去了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(); }