为什么不进行用户定义的转换
Why is this user-defined conversion not done?
考虑:
template<typename T>
struct Prop
{
T value;
operator T() { return value; }
};
int main()
{
Prop<float> p1 { 5 };
Prop<std::vector<float>> p2 { { 1, 2, 3 } };
float f1 = p1; // Works fine
float f2_1_1 = p2.value[0]; // Works fine
float f2_1_2 = p2[0]; // Doesn't compile
return 0;
}
为什么标记为这样的行没有编译?难道它不应该使用提供的转换运算符将std::vector<>
隐式转换为[]
吗?
这个网站上还有(许多)其他问题对这个问题提出了不同的要求,但我找不到一个我认为适用于这里的问题。是否与std::vector
作为模板有关?
成员函数调用的对象不考虑隐式转换,包括下标运算符重载。
如果允许的话,请考虑后果:每次像这样调用任何未声明的成员函数时,编译器都必须找出对象可以转换为的所有类型(请注意,任何其他不相关的类型都可能有转换构造函数),并检查它是否声明了丢失的成员函数。更不用说这会让代码的读者感到多么困惑(转换在转换运算符的情况下可能是显而易见的,但在转换构造函数的情况下则不然,据我所知,它们在其他方面没有区别对待)。
那么,有没有一种方便的方法可以让Prop按照我想要的表现
您必须为要透明传递的向量的每个成员函数定义一个成员函数。下面是下标运算符的例子:
auto operator[](std::size_t pos) {
return value[pos];
}
auto operator[](std::size_t pos) const {
return value[pos];
}
当然,问题是所有封装的成员函数都必须显式声明。另一个问题是参数的类型取决于T
。例如,vector::operator[]
使用vector::size_type
,这可能不是为您可能使用的所有T
定义的(当然不是为float
定义的)。在这里,我们做出妥协,使用std::size_t
。
创建这种"透明"包装器的一种不那么费力的方法是继承。一个公共继承模板将自动拥有父模板的所有成员函数,并且可以隐式转换为它,并且可以由父类型的指针和引用引用。然而,这种方法的透明度有点问题,主要是因为~vector
不是虚拟的。
私有继承允许与成员方法相同的包装,但语法要好得多:
template<typename T>
struct Prop : private T
{
using T::operator[];
using T::T;
};
请注意,继承方法防止您将基本类型用作T
。此外,它使隐式转换变得不可能(即使使用转换运算符),因此在需要T
的自由函数中不能将Prop
用作T
。
PS。请注意,转换运算符返回一个值,因此必须复制向量,这可能是不希望的。考虑提供参考版本:
operator T&&()&& { return *this; }
operator T&()& { return *this; }
operator const T&() const& { return *this; }
与任何
p2.size();
p2.begin();
p2.push_back(24);
// etc.
编译没有意义
还有
p2[0];
相当于
p2.operator[](0);
编译\没有意义
如果您想要这种行为(即Prop<T>
到借用T
成员),Bjarne提出了一个C++建议,将点运算符添加到语言中。我的工作方式与运算符->
处理智能指针的工作方式相同。AFAIR有很多争议,所以我不会为此屏住呼吸。
运营商网点提案的一点背景——Bjarne Stroustrup
操作员点(R3)-Bjarne Stroustrup,Gabriel Dos Rei
授权智能参考:N4477运营商Dot-Hubert Tong,Faisal Vali 的替代方案
操作员点的替代品-Bjarne Stroustrup
- Visual C++(VS2017)中用户定义的转换不明确
- 变量定义到C++布尔值转换
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 参数包构造函数在类模板中隐藏用户定义的转换
- C++:用户定义的显式类型转换函数错误
- 如何定义在用作函数参数时工作的类模板的转换
- 为什么转换函数声明不需要至少一个定义类型说明符
- 将文件复制到自定义位置,存在字符串转换问题
- 为什么从 char 转换为 std::byte 可能是未定义的行为?
- C++ 通过自定义赋值运算符隐式转换函数参数
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 用户定义的转换不能在C++中使用static_cast
- 用户定义的转换无法指定返回类型
- 如何在参数中定义隐式类型转换的构造函数?
- 是否可以创建一个用户定义的文本,将字符串文本转换为 own 类型的数组?
- 将结构 std::memcpy 转换为具有足够容量的 std::vector 是未定义的行为<char>吗?
- 在 C++ 中,我可以在不修改类的情况下定义对类的隐式转换吗?
- 过载分辨率和用户定义的转换
- 如何定义 typedefs 的隐式转换?
- 在unordered_map中,C2440"类型转换":无法转换...定义运算符 == 和hash_value时