如果我想获取我可以使用的数组的大小(元素数),sizeof(a) / sizeof(a[0])但新标准可以使用类型特征来做到这一点:
int main(){
int a[]{5, 7, 2, 3, 6, 7};
std::cout << std::extent<decltype(a)>::value << '\n'; // 6
auto& refA = a;
std::cout << std::extent<decltype(refA)>::value << '\n'; // 0
std::cout << sizeof(refA) / sizeof(refA[0]) << '\n'; // 6
std::cout << std::extent<std::remove_reference<decltype(refA)>::type>::value << '\n'; // 6
std::cout << "\ndone!\n";
}
Run Code Online (Sandbox Code Playgroud)
一切正常,但为什么不能std::extent像sizeof()运算符那样处理对数组的引用?我必须删除上一个示例中的引用才能获得实际的数组类型。
原因在于执行和标准背后的诚实;看看 GCC 的实现:
/// extent
template<typename, unsigned _Uint>
struct extent
: public integral_constant<std::size_t, 0> { };
template<typename _Tp, unsigned _Uint, std::size_t _Size>
struct extent<_Tp[_Size], _Uint>
: public integral_constant<std::size_t,
_Uint == 0 ? _Size : extent<_Tp,
_Uint - 1>::value>
{ };
template<typename _Tp, unsigned _Uint>
struct extent<_Tp[], _Uint>
: public integral_constant<std::size_t,
_Uint == 0 ? 0 : extent<_Tp,
_Uint - 1>::value>
{ };
Run Code Online (Sandbox Code Playgroud)
甚至cppreference中指定的可能实现:
template<class T, unsigned N = 0>
struct extent : std::integral_constant<std::size_t, 0> {};
template<class T>
struct extent<T[], 0> : std::integral_constant<std::size_t, 0> {};
template<class T, unsigned N>
struct extent<T[], N> : std::extent<T, N-1> {};
template<class T, std::size_t I>
struct extent<T[I], 0> : std::integral_constant<std::size_t, I> {};
template<class T, std::size_t I, unsigned N>
struct extent<T[I], N> : std::extent<T, N-1> {};
Run Code Online (Sandbox Code Playgroud)
T[]与数组的引用不同;所以它会退回到默认的,即:
template<class T, unsigned N = 0>
struct extent : std::integral_constant<std::size_t, 0> {};
Run Code Online (Sandbox Code Playgroud)
始终为 0。
也可以对其进行自定义以支持引用,但是您可能希望它支持const和volatile以及const volatile实现者(如果是我)像这样制作的其他内容(来自我的 web++ 项目):
WEBPP_REMOVE_CVREF()
WEBPP_REMOVE_CVREF(const)
WEBPP_REMOVE_CVREF(volatile)
WEBPP_REMOVE_CVREF(const volatile)
WEBPP_REMOVE_CVREF(&)
WEBPP_REMOVE_CVREF(&&)
WEBPP_REMOVE_CVREF(const&)
WEBPP_REMOVE_CVREF(const&&)
WEBPP_REMOVE_CVREF(volatile&)
WEBPP_REMOVE_CVREF(volatile&&)
WEBPP_REMOVE_CVREF(const volatile&)
WEBPP_REMOVE_CVREF(const volatile&&)
Run Code Online (Sandbox Code Playgroud)
是的,这样做不太漂亮,对吗?因此,实际上将其交给用户而不是库实现者或标准会更方便,通常也不会那么混乱。
| 归档时间: |
|
| 查看次数: |
74 次 |
| 最近记录: |