我想使用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 { templateT &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()
,我想知道是否有更多我不了解的替代方案?
我认为使用命名方法比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示例