在模板参数中使用静态 constexpr 成员数组作为指针
Using static constexpr member array as pointer in template parameters
以下main.cpp说明了问题:
#include <type_traits>
template <class T, std::size_t N>
struct Array
{
T data_[N];
};
template <const std::size_t* EltArray, std::size_t EltCount>
struct Foo
{
};
int main()
{
// SIDE NOTE if arr is not declared static: the address of 'arr' is not a valid template argument
// because it does not have static storage duration
static constexpr std::size_t arr[3] = {1, 2, 3};
Foo<arr, 3> foo;// WORKING
static constexpr Array<std::size_t, 3> arr2 = {1, 2, 3};
static constexpr const std::size_t* arr2_ptr = arr2.data_;
Foo<arr2_ptr, 3> foo2;// ERROR:
// 'arr2_ptr' is not a valid template argument of type 'const size_t*'
// {aka 'const long long unsigned int*'} because
// 'arr2.Array<long long unsigned int, 3>::data_' is not a variable
static constexpr const std::size_t* test = std::integral_constant<const std::size_t*, arr2_ptr>{};// ERROR:
// 'arr2_ptr' is not a valid template argument of type 'const long long unsigned int*' because
// 'arr2.Array<long long unsigned int, 3>::data_' is not a variable
return 0;
}
我不明白为什么 arr2.data_ 不能像 arr 一样重用。有人可以解释一下吗?
我正在使用 gcc:mingw-w64\x86_64-8.1.0-posix-sjlj-rt_v6-rev0
g++.exe -Wall -std=c++2a -fconcepts -O2
我想分享我刚刚在 open-std 中找到的答案和一个兼容的解决方案。
我们都知道我们不能将任何变量作为非类型传递。
你知道吗,我们可以将 const 引用传递给任何我们想要的东西?!
所以解是:
#include <array>
// When passing std::array<std::size_t, EltCount> (by value), i get the error:
// 'struct std::array<long long unsigned int, EltCount>' is not a valid type for a template non-type parameter
template <std::size_t EltCount, const std::array<std::size_t, EltCount>& Elts>
struct Foo {};
static constexpr std::array<std::size_t, 3> arr = {1, 2, 3};
int main()
{
Foo<3, arr> foo;// WORKING
return 0;
}
第一个问题的答案是:
N4296 的报价
14.3.2 模板非类型参数 [temp.arg.nontype]
对于引用或指针类型的非类型模板参数,
常量表达式的值不应引用(或对于指针类型,不应是地址):
(1.1) — 子对象 (1.8),
故事的寓意:我们可以用引用做我们想做的事,而不是用指针。
以下main.cpp说明了问题:
#include <type_traits>
template <class T, std::size_t N>
struct Array
{
T data_[N];
};
template <const std::size_t* EltArray, std::size_t EltCount>
struct Foo
{
};
int main()
{
// SIDE NOTE if arr is not declared static: the address of 'arr' is not a valid template argument
// because it does not have static storage duration
static constexpr std::size_t arr[3] = {1, 2, 3};
Foo<arr, 3> foo;// WORKING
static constexpr Array<std::size_t, 3> arr2 = {1, 2, 3};
static constexpr const std::size_t* arr2_ptr = arr2.data_;
Foo<arr2_ptr, 3> foo2;// ERROR:
// 'arr2_ptr' is not a valid template argument of type 'const size_t*'
// {aka 'const long long unsigned int*'} because
// 'arr2.Array<long long unsigned int, 3>::data_' is not a variable
static constexpr const std::size_t* test = std::integral_constant<const std::size_t*, arr2_ptr>{};// ERROR:
// 'arr2_ptr' is not a valid template argument of type 'const long long unsigned int*' because
// 'arr2.Array<long long unsigned int, 3>::data_' is not a variable
return 0;
}
我不明白为什么 arr2.data_ 不能像 arr 一样重用。有人可以解释一下吗?
我正在使用 gcc:mingw-w64\x86_64-8.1.0-posix-sjlj-rt_v6-rev0
g++.exe -Wall -std=c++2a -fconcepts -O2
我想分享我刚刚在 open-std 中找到的答案和一个兼容的解决方案。
我们都知道我们不能将任何变量作为非类型传递。
你知道吗,我们可以将 const 引用传递给任何我们想要的东西?!
所以解是:
#include <array>
// When passing std::array<std::size_t, EltCount> (by value), i get the error:
// 'struct std::array<long long unsigned int, EltCount>' is not a valid type for a template non-type parameter
template <std::size_t EltCount, const std::array<std::size_t, EltCount>& Elts>
struct Foo {};
static constexpr std::array<std::size_t, 3> arr = {1, 2, 3};
int main()
{
Foo<3, arr> foo;// WORKING
return 0;
}
第一个问题的答案是:
N4296 的报价
14.3.2 模板非类型参数 [temp.arg.nontype]
对于引用或指针类型的非类型模板参数, 常量表达式的值不应引用(或对于指针类型,不应是地址): (1.1) — 子对象 (1.8),
故事的寓意:我们可以用引用做我们想做的事,而不是用指针。