繁体   English   中英

是否可以为std :: array定义隐式转换运算符?

[英]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.2gcc-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM