为模板化类的[]运算符重载const版本

问题描述 投票:1回答:1

关于在C ++中重载[]运算符,特别是其const版本的另一个问题。

根据cppreference page on operator overloading,当重载数组下标运算符时

struct T
{
          value_t& operator[](std::size_t idx)       { return mVector[idx]; }
    const value_t& operator[](std::size_t idx) const { return mVector[idx]; }
};

如果已知值类型是内置类型,则const变体应按值返回。

因此,如果value_t 可能是内置类型,则const变体应该看起来

    const value_t operator[](std::size_t idx) const { return mVector[idx]; }

甚至可能

   value_t operator[](std::size_t idx) const { return mVector[idx]; }

因为const限定符在这样的返回值上不是很有用。


现在,我有一个模板化的class T(以保持与引用相同的命名),它与内置数据类型和用户定义的类型一起使用both,其中一些可能很重。

template<class VT>
struct T
{
          VT& operator[](std::size_t idx)       { return mVector[idx]; }
    const VT& operator[](std::size_t idx) const { return mVector[idx]; }
};

根据以上给出的建议,我应该将enable_if与某些type_traits一起使用,以区分具有内置/非内置类型的模板化类实例化。

我必须这样做吗?此建议是否为[[only,以避免对内置类型进行潜在的不必要的取消引用,或者隐藏在其中应引起注意的其他内容?


注:

    该类积极参与使用内置和自定义类型实例化的代码的热部分。
  • 代码与具有不同程度的优化选项的多个编译器跨平台使用。
  • 因此,我有兴趣使它既正确又可移植,并避免对性能造成任何潜在的损害。
  • 我无法在C ++标准中找到任何其他推理,但阅读
  • standardeze并不是我的最佳选择。

有关StackOverflow的现有问题:

c++ operator-overloading const c++17 built-in-types
1个回答
0
投票
您无需以特殊方式处理基本类型。只需始终为非const value_t变量返回value_t&,为const变量返回const value_t&

如您的示例中所示,重载通常很短,因此无论如何,它们将在每个呼叫站点内联。在那种情况下,重载返回按值还是按引用都没有关系,无论哪种情况,间接寻址都将被优化。任何设置为至少较低的优化级别的现代编译器都应这样做。

[我没有其他理由可以不同地处理基本类型。


我也要注意,如果您是如您的示例中那样实现容器类,返回引用和返回值将对用户具有不同的语义。

如果返回对元素的const引用,则用户可以保留该引用并观察容器元素的变化(直到引用失效以某种指定的方式发生)。如果返回值,则无法观察到更改。

如果用户能够获得参考并观察某些类型的未来变化,而其他类型则无法观察,这将令用户感到惊讶。最坏的情况是,如果他们也使用类型通用代码,则还需要对所有模板进行条件处理。

此外,即使您返回基本类型的按值,也仅通过对对象的const引用来调用返回按值的重载。在大多数情况下,用户可能具有您容器的非const实例,并且要利用这种潜在的优化方法,他们需要在调用成员函数之前先将其对象引用显式转换为const

因此,如果需要优化,我宁愿添加一个附加成员函数,该成员函数

always]返回容器元素按值的副本,并且如果潜在的取消引用被确定为性能问题,则用户可以使用该副本。调用此成员函数不会比确保调用正确的运算符重载更麻烦。

© www.soinside.com 2019 - 2024. All rights reserved.