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

C++ 是否可以使用-1获取容器/数组的最后一个元素?,c++,templates,c++11,operator-overloading,overloading,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<ty

我想要的说明如下:

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];
    }
}
模板
constexpr decltype(自动)运算符[](const C&coll,I idx)
{
如果(idx>=0)
{
返回coll[idx];
}
其他的
{
返回coll[std::size(coll)+idx];
}
}
但Clang抱怨说:

错误:重载的“运算符[]”必须是非静态成员函数

constexpr decltype(自动)运算符[](const C&coll,I idx)


<> P>是否可以正确实现现代C++中的函数?

,对于原始数组,不能超载<代码>运算符[] /COD>。 但您可以定义一些命名函数,例如,即兴:

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]); }

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

不能为原始数组重载
运算符[]

但您可以定义一些命名函数,例如,即兴:

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]); }

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

您还可以使用非成员
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);
}
模板
自动项(C常量和容器,int索引)->decltype(*std::cbegin(容器))
{
返回索引>=0?
*(标准::cbegin(容器)+索引):
*(标准::crbegin(容器)-索引-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;
std::vector coll{1,2,3,4};
int arra[]{10,20,30,40};
自动最后一个=项目(coll,-1);
auto secondLast=项目(coll,-2);
最后=项目(arra,-1);
第二个=项目(arra,-2);
返回0;

希望对您有所帮助:)

您还可以使用非成员的
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);
}
模板
自动项(C常量和容器,int索引)->decltype(*std::cbegin(容器))
{
返回索引>=0?
*(标准::cbegin(容器)+索引):
*(标准::crbegin(容器)-索引-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;
std::vector coll{1,2,3,4};
int arra[]{10,20,30,40};
自动最后一个=项目(coll,-1);
auto secondLast=项目(coll,-2);
最后=项目(arra,-1);
第二个=项目(arra,-2);
返回0;

希望对您有所帮助:)

您不能使用
运算符[]
,它必须是成员函数。如果(idx>=0),则条件可能是
。否则,
x[0]
将在数组末尾之外为您提供一个元素,这不会很好地结束:-)问题标题和内容不匹配。请将此注释修复并标记为已过时。请注意:
std::size(coll)+idx
将导致在
size\u t
范围内的环绕,因为C++17
std::size
的返回类型不切实际。您不能使用
运算符[]
,它必须是成员函数。如果(idx>=0),则条件可能是
。否则,
x[0]
将在数组末尾之外为您提供一个元素,这不会很好地结束:-)问题标题和内容不匹配。请修复此注释并将其标记为已过时。注意:
std::size(coll)+idx
将导致在
size\t
范围内的环绕,因为C++17
std::size
的返回类型不切实际。