微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么不能将作为常量引用传递给函数的数组的 .size() 用作模板参数?

如何解决为什么不能将作为常量引用传递给函数的数组的 .size() 用作模板参数?

我似乎无法弄清楚为什么以下代码不起作用:

#include <array>

template <long unsigned int s> void a() {}

template <long unsigned int s> void b(const std::array<int,s>& arr) {
    a<arr.size()>(); // error: no matching function for call to 'a'
}


int main() {
    const std::array<int,2> arr {{0,0}};
    a<arr.size()>(); // Works
    b<arr.size()>(arr);
    return 0;
}

GCC 失败并显示以下内容

test.cpp: In instantiation of ‘void b(const std::array<int,s>&) [with long unsigned int s = 2]’:
test.cpp:13:22:   required from here
test.cpp:6:18: error: no matching function for call to ‘a<(& arr)->std::array<int,2>::size()>()’
    6 |     a<arr.size()>(); // Doesn't
      |     ~~~~~~~~~~~~~^~
test.cpp:3:37: note: candidate: ‘template<long unsigned int s> void a()’
    3 | template <long unsigned int s> void a() {}
      |                                     ^
test.cpp:3:37: note:   template argument deduction/substitution Failed:
test.cpp:6:18: error: ‘arr’ is not a constant expression
    6 |     a<arr.size()>(); // Doesn't
      |     ~~~~~~~~~~~~~^~
test.cpp:6:15: note: in template argument for type ‘long unsigned int’
    6 |     a<arr.size()>(); // Doesn't
      |       ~~~~~~~~^~

我认为 ‘arr’ is not a constant expression 部分是最相关的,但我不明白为什么同一行在 main() 中起作用(它是一个常量表达式吗?),以及为什么传递 {{1} } 作为 arr 副本(而不是参考)也可以解决该问题。

PS:我知道我可以只使用 const,但我只是想弄清楚这个错误意味着什么。

解决方法

  1. 也许在 C++2X 中,它可以使用 consteval 函数。

  2. 对于非引用参数它有效 https://godbolt.org/z/Wx9va54z5。 我认为无论如何按值传递内置函数的 std::array 都很好。 (这适用于 GCC 和 clang。)

#include <array>

template <long unsigned int s> void a() {}

template <long unsigned int s> void b(std::array<int,s> arr) {
    a<arr.size()>(); // ok
}

int main() {
    const std::array<int,2> arr = {};
    a<arr.size()>(); // Works
    b<arr.size()>(arr);
    return 0;
}
  1. 要回答@acumandr 评论中的问题,是的,static 中的 constexprsize() std::array 成员函数会起作用(!),即使对于 {{ 1}} 论点。 https://godbolt.org/z/anP1e9qEr

更正:这仅适用于 GCC,在 clang 中不起作用 https://godbolt.org/z/65d5G9Yfo,谢谢@IlCapitano

const&

这更令人费解为什么 #include <array> template<class T,std::size_t D> struct MyArray{ static constexpr std::size_t size(){return D;} }; template <long unsigned int s> void a() {} template <long unsigned int s> void b(MyArray<int,s> const& arr) { a<arr.size()>(); // ok } int main() { const MyArray<int,2> arr = {}; a<arr.size()>(); // Works b<arr.size()>(arr); return 0; } 没有静态(和 constexpr)std::array 成员。

2.5) 更正:这仅适用于 GCC,在 clang 中不起作用 https://godbolt.org/z/65d5G9Yfo,谢谢@IlCapitano

在 clang 中,静态函数有效但不传递实例,这违背了目的:

https://godbolt.org/z/En13aEWPz

size
  1. 使用 #include <array> template<class T,s> const& arr) { a<std::decay_t<decltype(arr)>::size()>(); // error: no matching function for call to 'a' } int main() { const MyArray<int,2> arr = {}; a<arr.size()>(); // Works b<arr.size()>(arr); return 0; } (或 std::tuple_size<decltype(...)> 本身)是一个很好的解决方法 https://godbolt.org/z/K9xxKa1Px
s

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。