错误:“此”不是常量表达式

时间:2018-07-03 10:14:31

标签: c++ templates c++14 c++17 constexpr

我有带有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 ;
}

Run code

但是我确实需要在这种编译时上下文中使用方法。 我将在编译时对两个constexpr对象求和,因此我需要通过 get 方法来获得两个数据。

=======编辑=====

在@chris回答之后,我了解到我错过了一件事。 实际上,获取方法如下:

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

因此,代码处理对象的数据成员。

1 个答案:

答案 0 :(得分:1)

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对象一起使用时,它才能使您的原始示例编译。