是否可以使用-1来获取容器/数组的最后一个元素?

时间:2016-08-11 02:08:33

标签: c++ templates c++11 operator-overloading overloading

我想要的内容如下:

int array[4] { 1, 2, 3, 4 };
auto n1 = array[-1];
assert(4 == n1);
auto n2 = array[-2];
assert(3 == n2);

std::vector coll { 1, 2, 3, 4 };
auto n3 = coll[-1];
assert(4 == n3);
auto n4 = coll[-2];
assert(3 == n4);

我尝试了以下模板功能:

template<typename C, typename I>
constexpr decltype(auto) operator [](const C& coll, I idx)
{
    if (idx >= 0)
    {
        return coll[idx];
    }
    else
    {
        return coll[std::size(coll) + idx];
    }
}

但是Clang抱怨道:

  

错误:重载'operator []'必须是非静态成员函数

     

constexpr decltype(auto)operator [](const C&amp; coll,I idx)

是否可以在现代C ++中正确实现该功能?

2 个答案:

答案 0 :(得分:2)

您不能为原始数组重载operator[]

但是你可以定义一些命名函数,例如,关闭袖口:

using Index = ptrdiff_t;

template< class Item, size_t n >
auto item( Index const i, Item (&a)[n] )
    -> Item&
{ return (i < 0? a[Index( n ) + i] : a[i]); }

然后适当调整的原始数组的测试代码就像

int array[] { 1, 2, 3, 4 };
int n1 = item( -1, array );
assert( 4 == n1 );
int n2 = item( -2, array );
assert( 3 == n2 );

我为std::vector这样的一般集合留下了一个定义,作为读者的练习。 :)

答案 1 :(得分:1)

您还可以使用非成员std::begin()函数使上述解决方案更通用(至少对于标准序列容器)。例如:

template <typename C>
auto item(C const& container, int index) -> decltype(*std::cbegin(container))
{
    return index >= 0 ?
        *(std::cbegin(container) + index) :
        *(std::crbegin(container) - index - 1);
}

然后像这样使用它:

std::vector<int> coll{ 1, 2, 3, 4 };
int arra[] { 10, 20, 30, 40 };

auto last = item(coll, -1);
auto secondLast = item(coll, -2);

last = item(arra, -1);
secondLast = item(arra, -2);

return 0;

希望有所帮助:)