#c #constexpr
Вопрос:
Я представляю два фрагмента кода, один из которых компилируется, а другой-нет.
Тот, который не компилируется:
class Solution {
public:
const int MAX_NUM = 100;
const int MAX_SIZE = 200;
bool canPartition(vector<int>amp; 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>amp; 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
документацию и нашел две вещи, которые могут быть проблемой здесь:
constexpr должен быть немедленно инициализирован.
Он должен иметь постоянное разрушение, т. е. он не относится к классовому типу
Не могли бы вы указать, в чем здесь проблема, и помочь мне понять проблему?
Комментарии:
1. неявное использование указателя «this» разрешено только при оценке вызова функции-члена «constexpr». Этим все сказано, в вашей первой версии MAX_NUM и MAX_SIZE являются членами класса. И будет косвенно использовать указатель «это». Во второй версии вы используете локальные переменные (константы), и это отлично подходит для оценки размера набора битов (указатель «this» не требуется).
2. Намеревались ли вы разрешить
MAX_NUM
иMAX_SIZE
варьировать от объекта к объекту? Поскольку они естьconst
, они не могут быть изменены после построения, но (поскольку это неstatic
так ) конструктору будет разрешено инициализировать эти поля другими значениями на основе объекта за объектом (отсюда необходимость доступаthis
к ним через функцию-член, но это лакомый кусочек больше для ответа, чем для этого запроса на уточнение).3. Я понимаю. Спасибо @PKramer
4. Привет @JaMiT. Нет, я не собирался их менять. Я объявил их статичными, и это сработало! Теперь я понимаю ошибку. Спасибо всем за помощь.
Ответ №1:
Проблема в том, что, поскольку шаблоны оцениваются во время компиляции, их аргументы не могут быть чем-то таким, что компилятор не может «предсказать». В вашем первом коде переменные-члены 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
переменной в области действия функции это значение не может быть изменено и поэтому квалифицируется как аргумент шаблона, т. е. аналогично a constexpr
.
Ответ №2:
Сообщения об ошибках довольно хорошо объясняют, что происходит. Аргумент шаблона для объявления bits
должен быть постоянным выражением. Однако, если вы используете нестатические элементы, например MAX_NUM
, внутри функции-члена, не являющейся constexpr, вы в конечном итоге вычисляете this
указатель, что недопустимо. ссылка:
Базовым постоянным выражением является любое выражение, оценка которого не будет оценивать ни одно из следующих:
this
указатель, за исключением функции constexpr, которая вычисляется как часть выражения
Когда переменные типа MAX_NUM
объявляются внутри функции-члена, они не являются членами класса, и поэтому их можно использовать в качестве постоянных выражений, поэтому первая версия компилируется.
Комментарии:
1. Итак, похоже, что решение состоит в том , чтобы отметить
MAX_NUM
иMAX_SIZE
какstatic
, чтобы они не зависели отthis
указателя.2. @PeteBecker Да, это одно из решений. Хотя, если эти переменные больше нигде не используются, они также могут быть объявлены внутри функции-члена.