4

我正在尝试拥有一个可以隐式转换为std::array. 转换有效,但不是隐含的。

#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,如果没有更好的解决方案,我会接受。

4

2 回答 2

4

我从评论中回答你的问题:

您能否详细说明为什么我的转换没有意义?在尝试解析 operator[] 时,为什么编译器不考虑可能的转换?

简短的回答,因为这就是它的工作原理。可以在这里调用到内置类型的转换运算符,而不是用户定义的类型。

更长一点的答案:

在表达式中使用运算符时,重载决策遵循13.3.1.2.

第一的:

2 如果任一操作数的类型是类或枚举,则可能需要声明一个用户定义的操作符函数来实现该操作符,或者可能需要用户定义的转换将操作数转换为适合于构建的类型-in 运算符。在这种情况下,重载决策用于确定要调用哪个运算符函数或内置运算符来实现运算符 [...]。

a[1]是,为此目的解释为a.operator[](1),如同Table 11一节中所示。

然后按如下方式执行查找:

3 对于具有 cv 非限定版本为 T1 的类型的操作数的一元运算符 @,以及具有 cv 非限定版本为 T1 的类型的左操作数和 cv- 非限定版本的类型的右操作数的二元运算符 @不合格版本为T2,三组候选函数,指定成员候选、非成员候选和内置候选,构造如下:

— 如果 T1 是一个完整的类类型,则成员候选集是 T1::operator@ (13.3.1.1.1) 的合格查找的结果;否则,候选成员集合为空。[1]

— 非成员候选集是在表达式上下文中根据非限定函数调用 (3.4.2) 中名称查找的通常规则对 operator@ 进行非限定查找的结果,除了忽略所有成员函数。但是,如果没有操作数具有类类型,则只有查找集中具有 T1 类型的第一个参数或“对(可能是 cv 限定的)T1 的引用”的那些非成员函数,当 T1 是枚举类型时,或(如果有右操作数)类型 T2 的第二个参数或“对(可能是 cv 限定的)T2 的引用”,当 T2 是枚举类型时,是候选函数。 [2]

— 对于运算符 ,、一元运算符 & 或运算符 ->,内置候选集为空。对于所有其他运算符,内置候选函数包括 13.6 中定义的所有候选运算符函数,与给定运算符相比,

— 具有相同的运算符名称,并且
— 接受相同数量的操作数,并且
— 接受可以根据 13.3.3.1 将给定操作数转换为的操作数类型,并且[3]
— 不具有相同的参数类型-list 作为任何非模板非成员候选人。

结果如下:

  • [1]什么也没找到(operator[]你的课上没有
  • [2]什么也没找到(没有自由函数operator[],操作数都不是枚举类型)
  • [3]发现内置operator[](float*, std::ptrdiff_t)因为A声明转换为float*
于 2013-08-27T08:54:52.770 回答
3

您可以通过重载operator[]begin()onA或公开继承array(虽然不推荐)来让它们工作。

隐式转换仅在有意义时才有效(例如,如果您将 an 传递A给期望 a 的函数std::array<float, 7>),而不是您的情况。如果你问我,那是件好事。

于 2013-08-27T08:15:29.507 回答