首页 文章

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

提问于
浏览
0

我想要的是如下:

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&coll,I idx)

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

2 回答

  • 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

    您还可以使用非成员 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;
    

    希望有帮助:)

相关问题