当前位置:  开发笔记 > 编程语言 > 正文

方括号和圆括号操作符,如何选择超载?

如何解决《方括号和圆括号操作符,如何选择超载?》经验,为你挑选了1个好方法。

我想使用operator[]但是根据索引类型访问一些类数据返回一种数据或其他类型.作为简化示例:

struct S
{
    int   &operator []( int index ) { std::cout << "[i]"; return i_buffer[index]; }
    short &operator [](short index) { std::cout << "[s]"; return s_buffer[index]; }

private:
    int   i_buffer[10]{ 0,  1,   2,   3,   4,   5,   6,   7,   8,   9  };
    short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};

没有办法写一个short文字,所以选择short重载的唯一方法是通过强制转换:

S s;
std::cout << s[9] << '\n';        // prints [i]9
std::cout << s[(short)9] << '\n'; // prints [s]999

但我不喜欢它,我想知道是否有不同的选择.

我试过了什么?

标记参数.

首先我尝试使用" 标签 ":

struct S
{
    enum class i_type : std::int32_t {};
    enum class s_type : std::int32_t {};

    int   &operator [](i_type index)
    { std::cout << "[i]"; return i_buffer[static_cast(index)]; }
    short &operator [](s_type index)
    { std::cout << "[s]"; return s_buffer[static_cast(index)]; }

private:
    int   i_buffer[10]{ 0,  1,   2,   3,   4,   5,   6,   7,   8,   9  };
    short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};

这有效,但仍然有点冗长:

S s;
std::cout << s[9] << '\n';            // error, no possible overload to be taken
std::cout << s[S::i_type{9}] << '\n'; // prints [i]9
std::cout << s[S::s_type{9}] << '\n'; // prints [s]999

模板.

作为一个疯狂的解决方法,我想尝试模拟运算符:

struct S
{
    template 
    T &operator [](T) { std::cout << "???"; return 0; }

private:
    int   i_buffer[10]{ 0,  1,   2,   3,   4,   5,   6,   7,   8,   9  };
    short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};

template <>
int   &S::operator [](int index)   { std::cout << "[i]"; return i_buffer[index]; }
template <>
short &S::operator [](short index) { std::cout << "[s]"; return s_buffer[index]; }

模板版本的行为与原始代码相同,但是没有简单的方法来指定类型参数以及operator[]:

S s;
std::cout << s[9] << '\n';        // prints [i]9 like before
std::cout << s[(short)9] << '\n'; // prints [s]999 like before
std::cout << s[9] << '\n'; // s is not template
std::cout << s[9] << '\n'; // nonsense
// Correct but utterly verbose and hard to write and read
std::cout << s.operator[](9) << '\n';

题.

所描述的所有问题也随之发生operator(),我想知道是否有更多我不了解的替代方案?



1> Vittorio Rom..:

我认为使用命名方法operator[]在您的情况下使用更好,因为通过阅读源代码可以更容易理解访问两个单独的缓冲区.

无论如何,如果您想使用您的operator[]方法,您可以使用强类型定义用户定义的文字来使类型安全具有最小的语法开销:

BOOST_STRONG_TYPEDEF(std::size_t, int_index)
BOOST_STRONG_TYPEDEF(std::size_t, short_index)

struct S
{
    auto& operator[](int_index i) { /* ... */ }
    auto& operator[](short_index i) { /* ... */ }
};

auto operator "" _ii(unsigned long long int x) { return int_index{x}; }
auto operator "" _si(unsigned long long int x) { return short_index{x}; }

然后,您可以按如下方式调用方法:

S s;

auto& some_int = s[15_ii];
auto& some_short = s[4_si];

wandbox示例

推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有