gpt4 book ai didi

c++ - 为什么我的 constexpr 对象不在我的函数内?

转载 作者:行者123 更新时间:2023-12-01 19:31:38 25 4
gpt4 key购买 nike

我编写了一个可以在编译时初始化和复制的类,并且在我的函数之外使用对象也可以在编译时工作。现在我想将我的 constexpr 对象传递给函数来执行一些计算,但编译器会产生错误,指出我的对象不是常量表达式。

如何编写函数才能使用 constexpr 对象?

使用 GCC 9.2、C++17(激活使用 C++20 的 CLion 选项)

这是我的类、我的函数和主要内容。注意:并未给出所有定义,因为一篇文章的代码太多。

template<std::size_t t1_skipPos, std::size_t t2_skipPos, typename T1, typename T2>
constexpr auto contraction(T1 tensor1, T2 tensor2){

/*ERROR: tensor1 is not a constant expression*/
auto sris_tensor1 = save_recreated_index_sequence<0, tensor1.indices_amount-2,
t1_skipPos, tensor1.indices_amount, DIM3>(tensor1.calculate_indices());

return sris_tensor1;

}


template<typename T, typename ... Args>
class tensorBase{

private:
std::array<T, positive_natural_compiletime_pow<DIM3, std::tuple_size<Args...>::value>()> data;

public:
//std::vector<T> data = {};

std::tuple<Args...> myTypeTup;

std::size_t indices_amount = std::tuple_size<Args...>::value;


template<typename ... Element>
constexpr tensorBase(Element&&... input) : data{input...} {};

/* copy constructor */
template<typename Tensor>
constexpr tensorBase(const Tensor &oldObj){

data = oldObj.get_data();

myTypeTup = oldObj.myTypeTup;

indices_amount = oldObj.indices_amount;

}
/*
template<typename Arr>
constexpr tensorBase(Arr&& array) {
data = array;
};
*/
constexpr auto calculate_indices() const{

static_assert((std::tuple_size<Args...>::value <= 5), "tensor has to many indices");
//auto l = std::tuple_size<Args...>::value;
return cartesian_product<DIM3, std::tuple_size<Args...>::value>();
//return cartesian_product_to_vec<DIM3, sizeof...(Args)+1>();
};

template<typename D>
constexpr auto get_element(D&& val) const{
return data[val];
};

constexpr auto get_data() const{
return data;
};
};

template<typename T, typename ... Args>
using tensor = tensorBase<T, std::tuple<Args...>>;

int main(){
constexpr tensor<double, up_t, low_t, low_t> tensor1(11.0, 22.0, 33.0, 44.0, 55.0, 66.0, 77.0, 88.0, 99.0); /*OK*/
constexpr tensor<double, up_t, low_t> tensor2(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9);/*OK*/
constexpr auto copyObj1 = tensor1; /*OK*/
constexpr auto indices = tensor1.indices_amount; /*OK*/
constexpr auto indices1 = tensor1.calculate_indices(); /*OK*/

constexpr auto sris_outside = save_recreated_index_sequence
<0, tensor1.indices_amount-1,0,tensor1.indices_amount,2>(tensor1.calculate_indices()); /*OK*/

constexpr auto contract = contraction<0,0>(tensor1, tensor2); /*Error*/

return 0;
}

错误信息:

   In instantiation of ‘constexpr auto contraction(T1, T2) [with long unsigned int t1_skipPos = 0; long unsigned int t2_skipPos = 0; T1 = tensorBase<double, std::tuple<up_t, low_t, low_t> >; T2 = tensorBase<double, std::tuple<up_t, low_t> >]’:

error: no matching function for call to ‘save_recreated_index_sequence<0, (tensor1.tensorBase<double, std::tuple<up_t, low_t, low_t> >::indices_amount - 2), 0, tensor1.tensorBase<double, std::tuple<up_t, low_t, low_t> >::indices_amount, DIM3>(std::array<std::tuple<long unsigned int, long unsigned int, long unsigned int>, 27>)’
61 | auto sris_tensor1 = save_recreated_index_sequence<0, tensor1.indices_amount-2, t1_skipPos, tensor1.indices_amount, DIM3>(tensor1.calculate_indices());
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

note: candidate: ‘template<long unsigned int offset, long unsigned int N, long unsigned int skipPos, long unsigned int length, long unsigned int times, class Arr> constexpr auto save_recreated_index_sequence(Arr&&)’
46 | constexpr auto save_recreated_index_sequence(Arr&& arr){
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: template argument deduction/substitution failed:
In file included from /home/martin/CLionProjects/tensor-library-v1/main.cpp:43:
error: ‘tensor1’ is not a constant expression
61 | auto sris_tensor1 = save_recreated_index_sequence<0, tensor1.indices_amount-2, t1_skipPos, tensor1.indices_amount, DIM3>(tensor1.calculate_indices());
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in template argument for type ‘long unsigned int’
61 | auto sris_tensor1 = save_recreated_index_sequence<0, tensor1.indices_amount-2, t1_skipPos, tensor1.indices_amount, DIM3>(tensor1.calculate_indices());
| ~~~~~~~~~~~~~~~~~~~~~~^~
error: ‘tensor1’ is not a constant expression
61 | auto sris_tensor1 = save_recreated_index_sequence<0, tensor1.indices_amount-2, t1_skipPos, tensor1.indices_amount, DIM3>(tensor1.calculate_indices());
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in template argument for type ‘long unsigned int’
61 | auto sris_tensor1 = save_recreated_index_sequence<0, tensor1.indices_amount-2, t1_skipPos, tensor1.indices_amount, DIM3>(tensor1.calculate_indices());
| ~~~~~~~~^~~~~~~~~~~~~~
error: unable to deduce ‘auto’ from ‘sris_tensor1’
63 | return sris_tensor1;
| ^~~~~~~~~~~~
In function ‘int main()’:
error: ‘constexpr const void contract’ has incomplete type
162 | constexpr auto contract = contraction<0,0>(tensor1, tensor2);
| ^~~~~~~~

最佳答案

您需要通过tensor1作为模板参数,如果您想在需要常量表达式的上下文中使用它。目前(C++17)只能作为引用:

template<std::size_t t1_skipPos, std::size_t t2_skipPos, auto& tensor1, auto& tensor2>
constexpr auto contraction(){

auto sris_tensor1 = save_recreated_index_sequence<0, tensor1.indices_amount-2,
t1_skipPos, tensor1.indices_amount, DIM3>(tensor1.calculate_indices());

return sris_tensor1;

}

//...

constexpr auto contract = contraction<0, 0, tensor1, tensor2>();

但这也要求您声明 tensor1tensor2static ,使它们具有联系。否则,它们不能用作模板参数,并且会使该函数无法与非 constexpr 一起使用。变量。

请注意,C++20 添加了类类型的非类型模板参数,这可能会使引用变得不必要,因此也不需要链接的要求(通过使用 auto 而不是 auto& ),但这并不适用于 C++20 草案当前状态下的类,该草案要求该类型的所有非静态数据成员都是公共(public)的。此要求最近已更改,因此当前编译器版本在使用 -std=c++2a 时可能会实现先前草案版本的不太严格的要求。 ,其中您的类将是类类型的有效非类型模板参数。

您不能在需要常量表达式的上下文中使用函数参数。该上下文出现在另一个常量表达式求值中这一事实并不重要。一个constexpr函数还必须始终是有效的运行时函数。

<小时/>

在所示代码的特定情况下,您可以改为 indices_amount一个static类的成员并通过类型访问该成员,以便函数参数的状态永远不会在常量表达式上下文中使用:

static constexpr std::size_t indices_amount = std::tuple_size_v<Args...>;

//...

template<std::size_t t1_skipPos, std::size_t t2_skipPos, typename T1, typename T2>
constexpr auto contraction(T1 tensor1, T2 tensor2){

/*ERROR: tensor1 is not a constant expression*/
auto sris_tensor1 = save_recreated_index_sequence<0, T1::indices_amount-2,
t1_skipPos, T1::indices_amount, DIM3>(tensor1.calculate_indices());

return sris_tensor1;

}
<小时/>

另请注意,您的 tensorBase 似乎没有任何意义。有一个参数包作为第二个模板参数。它只填充了一个参数,并且也不适用于任何其他数字。例如std::tuple_size<Args...>仅当包中只有一个元素时才有效。我建议你删除所有...Args 相关在那个类(class)。

关于c++ - 为什么我的 constexpr 对象不在我的函数内?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59841301/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com