我展示了两个代码片段,其中一个编译,另一个不编译。
没有编译的:
class Solution {
public:
const int MAX_NUM = 100;
const int MAX_SIZE = 200;
bool canPartition(vector<int>& nums) {
bitset<(MAX_NUM*MAX_SIZE)/2 + 1> bits(1);
int sum = 0;
for(int num: nums)
{
sum += num;
bits |= bits << num;
}
return !(sum % 2) and bits[sum/2];
}
};给出错误:
error: non-type template argument is not a constant expression
implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function
这样做的人:
class Solution {
public:
bool canPartition(vector<int>& nums) {
const int MAX_NUM = 100;
const int MAX_SIZE = 200;
bitset<(MAX_NUM*MAX_SIZE)/2 + 1> bits(1);
int sum = 0;
for(int num: nums)
{
sum += num;
bits |= bits << num;
}
return !(sum % 2) and bits[sum/2];
}
};我阅读了constexpr文档,并在这里发现了可能有问题的两件事:
必须立即初始化。它必须有不断的破坏,即它不是类类型的。
你能指出这里有什么问题并帮助我理解问题吗?
发布于 2021-09-11 19:05:17
问题是,由于模板是在编译时计算的,它们的参数不可能是编译器无法“预测”的内容。在第一段代码中,成员变量MAX_NUM和MAX_SIZE是const值,这意味着在创建类Solution的实例并对它们进行初始化之后不能更改它们。但是对于每个Solution实例,仍然可以在构造函数中使用不同的不可预测的值初始化它们。您将其设置为等于(分别为100和200)的默认值只有在创建实例时未初始化时才使用。看看下面的代码:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
class A
{
private:
const int m_foo = 1;
public:
A() {}
A(int num) : m_foo(num) {}
int foo() { return m_foo; }
};
int main()
{
A a1; //a1.m_foo initialized with default value
cout << "Enter desired m_foo for a2: ";
int foo;
cin >> foo;
A a2(foo); //a2.m_foo initialized with user input
cout << "m_foo for a1: " << a1.foo() << endl
<< "m_foo for a2: " << a2.foo();
return 0;
}如您所见,const成员变量m_foo可以是用户输入的任何值。
但是,在函数范围内定义const变量时,不能更改该值,因此可以将其限定为模板参数,即它类似于constexpr。
发布于 2021-09-11 18:15:57
错误信息很好地解释了发生了什么。bits声明的模板参数需要是一个常量表达式。但是,如果在非参数成员函数中使用非静态成员(如MAX_NUM ),则最终要计算this指针,这是不允许的。参考
核心常量表达式是计算值不计算下列任何一项的任何表达式:
this指针,除非在作为表达式的一部分进行计算的constexpr函数中。当像MAX_NUM这样的变量在成员函数中声明时,它们不是类的成员,因此它们可以用作常量表达式,这就是第一个版本编译的原因。
https://stackoverflow.com/questions/69145522
复制相似问题