gpt4 book ai didi

c++ - 方括号和圆括号运算符,如何选择重载?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:18:12 26 4
gpt4 key购买 nike

我想使用 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<int>(index)]; }
short &operator [](s_type index)
{ std::cout << "[s]"; return s_buffer[static_cast<int>(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 <typename T>
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<short>[9] << '\n'; // s is not template
std::cout << s[9]<short> << '\n'; // nonsense
// Correct but utterly verbose and hard to write and read
std::cout << s.operator[]<short>(9) << '\n';

问题。

所描述的所有问题也发生在 operator() 中,我想知道是否还有更多我不知道的替代方法?

最佳答案

我认为在您的情况下使用命名方法 比使用operator[] 要好得多,因为两个单独的缓冲区是通过阅读源代码访问。

无论如何,如果您想使用operator[] 方法,您可以使用strong typedefsuser defined literals以最小的语法开销实现类型安全:

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 example

关于c++ - 方括号和圆括号运算符,如何选择重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41849671/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com