【发布时间】:2020-06-23 13:13:07
【问题描述】:
我使用std::array 作为在编译时表示具有固定长度的向量的基础,并希望使用std::array::size 作为constexpr 函数来禁用1D 和@987654328 的叉积计算@ 向量。
当我在非 constexpr 函数中使用 std::array::size 时,它将我的向量作为左值参数,我得到一个错误:
main.cpp: In instantiation of ‘VectorType cross(const VectorType&, const VectorType&) [with VectorType = Vector<double, 3>]’:
main.cpp:97:16: required from here
main.cpp:89:62: error: ‘vec1’ is not a constant expression
89 | return cross_dispatch<std::size(vec1), VectorType>::apply(vec1, vec2);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
main.cpp:89:36: note: in template argument for type ‘long unsigned int’
89 | return cross_dispatch<std::size(vec1), VectorType>::apply(vec1, vec2);
|
这是main 函数的最小工作示例:
#include <array>
#include <iostream>
using namespace std;
template<typename AT, auto D>
class Vector final
:
public std::array<AT, D>
{
public:
using container_type = std::array<AT,D>;
using container_type::container_type;
template<typename ... Args>
constexpr Vector(Args&& ... args)
:
container_type{std::forward<Args>(args)...}
{}
// Delete new operator to prevent undefined behavior for
// std::array*= new Vector; delete array; std::array has
// no virtual destructors.
template<typename ...Args>
void* operator new (size_t, Args...) = delete;
};
using vector = Vector<double, 3>;
template<std::size_t DIM, typename VectorType>
struct cross_dispatch
{
static VectorType apply(VectorType const& v1, VectorType const& v2)
{
static_assert(std::size(v1) < 3, "Cross product not implemented for 2D and 1D vectors.");
static_assert(std::size(v1) > 3, "Cross product not implemented for ND vectors.");
return VectorType();
}
};
template<typename VectorType>
struct cross_dispatch<3, VectorType>
{
static VectorType apply(VectorType const& v1, VectorType const& v2)
{
return VectorType(v1[1]*v2[2] - v1[2]*v2[1],
v1[2]*v2[0] - v1[0]*v2[2],
v1[0]*v2[1] - v1[1]*v2[0]);
}
};
template <typename VectorType>
VectorType cross(VectorType const& vec1, VectorType const& vec2)
{
return cross_dispatch<std::size(vec1), VectorType>::apply(vec1, vec2);
}
int main()
{
vector p1 {1.,2.,3.};
vector q1 {1.,2.,3.};
cross(p1,q1);
}
我发现 this question 提到了 GCC 8.0 中的一个错误,但我使用的是 g++ (GCC) 10.1.0。
表达式 e 是一个核心常量表达式,除非 e,遵循抽象机(6.8.1)的规则,将评估 以下表达式之一:
... 一个 id 表达式,它引用一个变量或数据成员 引用类型,除非该引用具有前面的初始化和 要么是用常量表达式初始化,要么是它的生命周期 开始内评估e
这是否意味着,在人类(非标准)语言中,在我的表达式 e:=cross(p1,p2)、p1 和 p2 之前未初始化为 constexpr 及其生命周期没有以e开头,所以即使p1和p2是一种数据类型的对象,其大小在编译时是已知的,其mfunction size是 constexpr mfunction,我现在必须将它们声明为 constexpr,然后才能将它们绑定为不是 constexpr 的函数中的左值?
【问题讨论】:
-
这不是特别小,问题标题谈到
if constexpr,但在这个例子中没有if constexpr? -
嗯,tl;博士。但是,您可以将
static constexpr size_t size() { return D; }添加到您的Vector并执行return cross_dispatch<VectorType::size(), VectorType>::apply(vec1, vec2);以解决此特定问题。 -
我编辑了标题,有另一个带有
if constexpr的函数模板,但我最终使用了cross。Vector是否也没有从std::array继承static constexpr size_t size(),还是我忘记了另一条规则? -
std::array::size()真的是静态的吗?我不认为它是 - 即使是,我认为通过实例 (std::size(vec1)) 调用它也行不通,你必须像VectorType::size()那样调用它 -
你会对这篇博文感兴趣The constexpr array size problem,作者是第一个评论者! @巴里
标签: c++ constexpr c++20 if-constexpr