ошибка: это не постоянное выражение - PullRequest
0 голосов
/ 03 июля 2018

У меня есть конструктор объекта constexpr с методами constexpr.

// My SparseArray implementation

#include <cstdint>
#include <iostream>
#include <utility>

template<typename T, uint64_t size>
class SparseArray 
{
    public:
    using ElementType = T;

    template<typename... Args>
    constexpr SparseArray(Args&&... args) 
    : values{args...} {
        std::cout << "Args ctor." << '\n';
    }

    template<uint8_t Index>
    constexpr ElementType get() const {
        // some logic
        return T();
    }

    constexpr auto someMethod() {
        get<0>();                                            // <--------- works fine
        auto seq  = std::integer_sequence<ElementType, 0>{}; // <--------- works fine
        auto seq2 = std::integer_sequence<ElementType, get<0>()>{}; // <-- error
    }

    ElementType values[size];  
};

int main ()
{
    SparseArray<int, 3> array(1, 2, 3);
    array.someMethod();

    return 0 ;
}

Код прогона

Но мне действительно нужно использовать метод в таком контексте во время компиляции. Я собираюсь суммировать два объекта constexpr во время компиляции, поэтому мне нужно получить данные обоих благодаря методу get .

======= Edited =====

После ответа @chris я понял, что упустил одну вещь. На самом деле get метод выглядит так:

    template<uint8_t Index>
    constexpr ElementType get() const {
        if(/*some logic*/)
            return values[/*some logic*/];
        else
            return T();
    }

Итак, код имеет дело с элементом данных объекта.

1 Ответ

0 голосов
/ 03 июля 2018

constexpr функции должны использоваться во время компиляции и выполнения. Вы вызываете нестатическую функцию-член, поэтому она должна работать независимо от того, известен ли объект класса во время компиляции. Если требуется, чтобы объект был известен во время компиляции, функция больше не работает во время выполнения.

Самый простой способ обойти это - использовать функцию, которая не зависит от неиспользуемого объекта класса:

template<uint8_t Index>
static constexpr ElementType get() {
    // some logic
    return T();
}

Если это не вариант, потому что вы используете объект класса, то вам нужно убедиться, что объект является constexpr для его использования:

constexpr SparseArray<int, 3> array(1, 2, 3);
auto seq2 = std::integer_sequence<int, array.get<0>()>{};

Независимо от того, где вы используете get, единственный способ использования результата в качестве значения времени компиляции - это если все параметры, включая объект, являются значениями времени компиляции.

EWG приняла constexpr! для принудительной оценки функции во время компиляции, но ваш исходный пример не будет скомпилирован, пока не будет использован объект constexpr SparseArray.

...