Как вызвать оператор с constexpr без использования временных переменных?

Следующий пример кода иллюстрирует мою проблему.

constexpr int fact(int N) {
    return N ? N * fact(N - 1) : 1;
}
struct A {
    int d;
    constexpr A operator+(const A& other) const { return A{ fact(d + other.d) }; }
    // overload of many other operators
};

int main() {
    int x;
    cin >> x;                       // run time argument

    constexpr A a{ 2 }, b{ 3 };
    A c{ x };

    A u = a + b + c;                // both + eval at run time
    //constexpr A v = a + b + c;    // doesn't compile because c is not constant
}

Чего я хочу добиться, так это того, чтобы первый operator+ оценивался во время компиляции, а второй operator+ оценивался во время выполнения.

конечно можно разбить на

constexpr A tmp = a + b;
A u = tmp + c;

но в моем случае весь смысл перегрузки операторов состоит в том, чтобы позволить создавать более сложные формулы более интуитивным способом, что сделало бы перегрузку бессмысленной.

Если я объявлю operator+ как consteval, то он снова не скомпилируется. И я не могу перегрузить его дважды.

Есть ли решение?

он оценивается во время компиляции godbolt.org/z/7PYY1cjnv, если вы включаете оптимизацию.

apple apple 09.04.2022 11:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Нет, по крайней мере, в gcc и с оптимизацией здесь вы можете увидеть, как он оценивается во время компиляции. (120)

main:
        mov     eax, 1
        add     edi, 120
        je      .L4
.L3:
        imul    eax, edi
        sub     edi, 1
        jne     .L3
        ret
.L4:
        ret

*Справедливости ради, даже без constexpr компилятор, вероятно, также оптимизировал бы его.

Однако это решение компилятора, которое не гарантируется языком. В сборке выпуска VS2019 мой код дизассемблирования показывает, что оба оцениваются во время выполнения. Я хотел бы знать, можно ли добиться такого же эффекта, как разбить его на constexpr A tmp = a + b; A u = tmp + c;, не завися от компилятора.

WhatsUp 09.04.2022 11:51

@WhatsUp не работает, даже если вы пишете это таким образом, компилятор не является обязательный для оценки этого во время компиляции (хотя mscv выполняет это во время компиляции)

apple apple 09.04.2022 12:01

Да я понимаю, что не принудительно. Но, по крайней мере, я делаю все возможное, чтобы заставить компилятор сделать это...

WhatsUp 09.04.2022 13:14
Ответ принят как подходящий

Вы можете принудительно выполнить оценку с помощью (нетипового) параметра шаблона или функции consteval.

constexpr int fact(int N) {
    return N ? N * fact(N - 1) : 1;
}
struct A {
    int d;
    constexpr A operator+(const A& other) const { return A{ fact(d + other.d) }; }
};

consteval auto value(auto v){return v;}

A foo (int x) {

    constexpr A a{ 2 }, b{ 3 };
    A c{ x };

    A u = value(a+b) + c;
    return u;
}

https://godbolt.org/z/ohf61vebv

Другие вопросы по теме