为什么不能将作为常量引用传递给函数的数组的 .size() 用作模板参数?
Why can't the .size() of an array passed to a function as a constant reference be used as a template parameter?
我似乎无法弄清楚为什么以下代码不起作用:
#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()
中有效(那里是常量表达式吗?),以及为什么传递 arr
作为 const
副本(而不是参考)也解决了这个问题。
PS:我知道我可以直接使用 a<s>();
,但我只是想弄清楚这个错误是什么意思。
也许在 C++2X 中,它将与 consteval
函数一起工作。
对于非引用参数它有效 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;
}
- 要回答您评论@acumandr 中的问题,是的,
static
和 constexpr
size()
成员函数 std::array
可以工作(!),即使const&
参数。 https://godbolt.org/z/anP1e9qEr
CORRECTION: This is correct only for GCC, in clang doesn't work https://godbolt.org/z/65d5G9Yfo , Thanks @IlCapitano
#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;
}
这更令人困惑为什么 std::array
没有静态(和 constexpr)size
成员。
2.5) 更正:这仅适用于 GCC,在 clang 中不起作用 https://godbolt.org/z/65d5G9Yfo,谢谢 @IlCapitano
在 clang 中,静态函数有效但不传递实例,这违背了目的:
https://godbolt.org/z/En13aEWPz
#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<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(...)>
(或s
本身)是一个很好的解决方法https://godbolt.org/z/K9xxKa1Px
#include <array>
template <long unsigned int s> void a() {}
template <long unsigned int s> void b(std::array<int, s> arr) {
a<std::tuple_size<decltype(arr)>::value /*or just s*/>(); // ok
}
int main() {
const std::array<int, 2> arr = {};
a<arr.size()>(); // Works
b<arr.size()>(arr);
return 0;
}
我似乎无法弄清楚为什么以下代码不起作用:
#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()
中有效(那里是常量表达式吗?),以及为什么传递 arr
作为 const
副本(而不是参考)也解决了这个问题。
PS:我知道我可以直接使用 a<s>();
,但我只是想弄清楚这个错误是什么意思。
也许在 C++2X 中,它将与
consteval
函数一起工作。对于非引用参数它有效 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;
}
- 要回答您评论@acumandr 中的问题,是的,
static
和constexpr
size()
成员函数std::array
可以工作(!),即使const&
参数。 https://godbolt.org/z/anP1e9qEr
CORRECTION: This is correct only for GCC, in clang doesn't work https://godbolt.org/z/65d5G9Yfo , Thanks @IlCapitano
#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;
}
这更令人困惑为什么 std::array
没有静态(和 constexpr)size
成员。
2.5) 更正:这仅适用于 GCC,在 clang 中不起作用 https://godbolt.org/z/65d5G9Yfo,谢谢 @IlCapitano
在 clang 中,静态函数有效但不传递实例,这违背了目的:
https://godbolt.org/z/En13aEWPz
#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<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(...)>
(或s
本身)是一个很好的解决方法https://godbolt.org/z/K9xxKa1Px
#include <array>
template <long unsigned int s> void a() {}
template <long unsigned int s> void b(std::array<int, s> arr) {
a<std::tuple_size<decltype(arr)>::value /*or just s*/>(); // ok
}
int main() {
const std::array<int, 2> arr = {};
a<arr.size()>(); // Works
b<arr.size()>(arr);
return 0;
}